rk312x:rt5025:support pmic rt5025
author张晴 <zhangqing@rock-chips.com>
Fri, 22 Aug 2014 02:01:21 +0000 (10:01 +0800)
committer张晴 <zhangqing@rock-chips.com>
Fri, 22 Aug 2014 02:01:21 +0000 (10:01 +0800)
36 files changed:
Documentation/devicetree/bindings/mfd/rt5025.txt [new file with mode: 0755]
Documentation/devicetree/bindings/power/rt5025-battery.txt [new file with mode: 0755]
Documentation/devicetree/bindings/power/rt5025-charger.txt [new file with mode: 0755]
Documentation/devicetree/bindings/regulator/rt5025-regulator.txt [new file with mode: 0755]
arch/arm/boot/dts/rk312x-sdk.dtsi
arch/arm/boot/dts/rt5025.dtsi [new file with mode: 0755]
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-rt5025.c [new file with mode: 0755]
drivers/gpio/rt5025-gpio.c [deleted file]
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/rt5025-core.c [changed mode: 0644->0755]
drivers/mfd/rt5025-debug.c [changed mode: 0644->0755]
drivers/mfd/rt5025-i2c.c [changed mode: 0644->0755]
drivers/mfd/rt5025-irq.c [changed mode: 0644->0755]
drivers/mfd/rt5025-misc.c [changed mode: 0644->0755]
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/rt-power.c [new file with mode: 0755]
drivers/power/rt5025-battery.c [changed mode: 0644->0755]
drivers/power/rt5025-charger.c [new file with mode: 0755]
drivers/power/rt5025-power.c [changed mode: 0644->0755]
drivers/power/rt5025-swjeita.c [changed mode: 0644->0755]
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/rt5025-regulator.c
include/linux/mfd/rt5025-gpio.h
include/linux/mfd/rt5025-irq.h [changed mode: 0644->0755]
include/linux/mfd/rt5025-misc.h [changed mode: 0644->0755]
include/linux/mfd/rt5025.h [changed mode: 0644->0755]
include/linux/power/rockchip-general-bat.h
include/linux/power/rt-power.h [new file with mode: 0755]
include/linux/power/rt5025-battery.h [changed mode: 0644->0755]
include/linux/power/rt5025-charger.h [new file with mode: 0755]
include/linux/regulator/rt5025-regulator.h [changed mode: 0644->0755]

diff --git a/Documentation/devicetree/bindings/mfd/rt5025.txt b/Documentation/devicetree/bindings/mfd/rt5025.txt
new file mode 100755 (executable)
index 0000000..8b0865f
--- /dev/null
@@ -0,0 +1,74 @@
+Richtek RT5025 Multi-functional device
+
+The RT5025 are Integrated Power Management Chips.
+These chips are connected to an i2c bus.
+
+
+Required properties:
+- compatible : Must be "rt,rt5025";
+- interrupts : This i2c device has an IRQ line connected to the main SoC
+- interrupt-parent : The parent interrupt controller.
+
+Optional node:
+- Child nodes contain in the RT5025. The twl family is made of several variants
+  that support a different number of features.
+
+
+Example:
+rt5025@35 {
+       compatible = "rt,rt5025";
+       reg = <0x35>;
+       interrupt-parent = <&msmgpio>;
+       interrupts = <73 0>;
+
+       rt5025_dcdc1: regulator_0 {
+               compatible = "rt,rt5025-dcdc1";
+               cell-index = <0>;
+               regulator-name = "rt5025-dcdc1";
+               regulator-min-microvolt = < 700000>;
+               regulator-max-microvolt = <2275000>;
+               rt,ramp_sel = <0x00>;
+               rt,allow_mode_mask;
+               qcom,comsumer-supplies = "rt5025-dcdc1", "";
+       };
+
+       rt5025-charger {
+               compatible = "rt,rt5025-charger";
+               rt,te_en;
+               //rt,screenon_adjust;
+               rt,iprec = <0x00>;
+               rt,ieoc = <0x00>;
+               rt,vprec = <0x05>;
+               rt,vdpm = <0x02>;
+               rt,chg_volt = <4200>;
+               rt,acchg_icc = <2000>;
+               rt,usbtachg_icc = <2000>;
+               rt,usbchg_icc = <500>;
+               rt,screenon_icc = <500>;
+               rt,temp = <0 150 500 600>;
+               rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
+       };
+
+       rt5025_gpiop: rt5025-gpio {
+               compatible = "rt,rt5025-gpio";
+               gpio-controller;
+               #gpio-cells = <2>;
+               rt,ngpio = <3>;
+       };
+
+       rt5025-irq {
+               compatible = "rt,rt5025-irq";
+               rt,irq-gpio = <&msmgpio 73 0x00>;
+       };
+
+       rt5025-misc {
+               compatible = "rt,rt5025-misc";
+               rt,system_lv = <0x02>;
+               rt,shdn_lpress = <0x01>;
+               rt,start_lpress = <0x00>;
+               rt,syslv_enshutdown;
+       };
+
+       rt5025-debug {
+               compatible = "rt,rt5025-debug";
+       };
diff --git a/Documentation/devicetree/bindings/power/rt5025-battery.txt b/Documentation/devicetree/bindings/power/rt5025-battery.txt
new file mode 100755 (executable)
index 0000000..2b9f4a9
--- /dev/null
@@ -0,0 +1,14 @@
+Richtek RT5025 battery/fuelgauge function
+
+The RT5025 battery is responsible to report the battery voltage/current
+, capacity, etc.
+
+Required properties:
+
+ - compatible : Must be "rt,rt5025-battery".
+
+Example:
+
+rt5025-battery {
+       compatible = "rt,rt5025-battery";
+};
diff --git a/Documentation/devicetree/bindings/power/rt5025-charger.txt b/Documentation/devicetree/bindings/power/rt5025-charger.txt
new file mode 100755 (executable)
index 0000000..b94e36c
--- /dev/null
@@ -0,0 +1,41 @@
+Richtek RT5025 Charger part
+
+The RT5025 charger part is responsible to change the charging current/voltage, etc.
+
+Required properties:
+
+ - compatible : Must be "rt,rt5025-charger".
+ - rt,chg_volt : default charging voltage.
+ - rt,ieoc : 0x0 is 10%, 0x1 is 20%.
+ - rt,vdpm : 0x0 is 4V, 0x1 is 4.25V, 0x2 is 4.5V, 0x3 is disable.
+ - rt,vprec: precharge voltage.
+ - rt,iprec: precharge current.
+ - rt,acchg_icc: rt-power ac charge current.
+ - rt,usbtachg_icc: rt-power usbta charge current.
+ - rt,ustchg_icc: rt-power normal usb charge current.
+ - rt,screenon_icc: screen on charge current.
+ - rt,te_en: enable terminate function.
+ - rt,screenon_adjust: enable screen on lower charge current,
+               screen off recovery to the default charge current.
+ - rt,temp: jeita temperature, unit 0.1'c
+ - rt,temp_scalar: jeita temperature scalar according to NTC spec.
+
+Example:
+
+                       rt5025-charger {
+                               compatible = "rt,rt5025-charger";
+                               rt,te_en;
+                               //rt,screenon_adjust;
+                               rt,iprec = <0x00>;
+                               rt,ieoc = <0x00>;
+                               rt,vprec = <0x05>;
+                               rt,vdpm = <0x02>;
+                               rt,chg_volt = <4200>;
+                               rt,acchg_icc = <2000>;
+                               rt,usbtachg_icc = <2000>;
+                               rt,usbchg_icc = <500>;
+                               rt,screenon_icc = <500>;
+                               rt,temp = <0 150 500 600>;
+                               rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
+                       };
+
diff --git a/Documentation/devicetree/bindings/regulator/rt5025-regulator.txt b/Documentation/devicetree/bindings/regulator/rt5025-regulator.txt
new file mode 100755 (executable)
index 0000000..d9073c7
--- /dev/null
@@ -0,0 +1,27 @@
+Richtek RT5025 of regulators
+
+Required properties:
+For rt5025 regulators/LDOs
+- compatible:
+  - "rt,rt5025-dcdc1" for Buck1
+  - "rt,rt5025-dcdc2" for Buck2
+  - "rt,rt5025-dcdc3" for Buck3
+  - "rt,rt5025-dcdc4" for Buck4/Boost
+  - "rt,rt5025-ldo1" for Ldo1
+  - "rt,rt5025-ldo2" for Ldo2
+  - "rt,rt5025-ldo3" for Ldo3
+  - "rt,rt5025-ldo4" for Ldo4
+  - "rt,rt5025-ldo5" for Ldo5
+  - "rt,rt5025-ldo6" for Ldo6
+
+Example:
+
+       rt5025-dcdc1: regulator_0@0 {
+               compatible = "rt,rt5025-dcdc1";
+               cell-index = <0>;
+               regulator-min-microvolt  = < 700000>;
+               regulator-max-microvolt  = <2275000>;
+               rt,ramp_sel = <0x00>;
+               rt,allow_mode_mask;
+               qcom,consumer-supplies = "rt5025-dcdc1", "";
+       };
index 6e305d4063f981a5e6b0973a9df43135bb86568d..35c23765dd79c973585cfd140fee50774a30ca6b 100755 (executable)
                reg = <0x1c>;
                status = "okay";
        };
+       rt5025: rt5025@35 {
+                       compatible = "rt,rt5025";
+                       reg = <0x35>;
+                       status = "okay";
+       };
 };
 &i2c2 {
        status = "okay";
        status = "okay";
 };
 
+/include/ "rt5025.dtsi"
+&rt5025 {
+
+                       rt5025_dcdc1: regulator_0 {
+                               regulator-name = "vdd_arm";
+                               regulator-min-microvolt = < 700000>;
+                               regulator-max-microvolt = <1500000>;
+                               qcom,comsumer-supplies = "vdd_arm", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+
+                       };
+
+                       rt5025_dcdc2: regulator_1 {
+                               regulator-name = "vdd_logic";
+                               regulator-min-microvolt = < 700000>;
+                               regulator-max-microvolt = <1500000>;
+                               qcom,comsumer-supplies = "vdd_logic", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_dcdc3: regulator_2 {
+                               regulator-name = "rt5025-dcdc3";
+                               regulator-min-microvolt = < 1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               qcom,comsumer-supplies = "rt5025-dcdc3", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_dcdc4: regulator_3 {
+                               regulator-name = "rt5025-dcdc4";
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5000000>;
+                               qcom,comsumer-supplies = "rt5025-dcdc4", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo1: regulator_4 {
+                               regulator-name = "rt5025-ldo1";
+                               regulator-min-microvolt = < 1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               qcom,comsumer-supplies = "rt5025-ldo1", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo2: regulator_5 {
+                               regulator-name = "rt5025-ldo2";
+                               regulator-min-microvolt = < 1200000>;
+                               regulator-max-microvolt = <1200000>;
+                               qcom,comsumer-supplies = "rt5025-ldo2", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo3: regulator_6 {
+                               regulator-name = "rt5025-ldo3";
+                               regulator-min-microvolt = <2800000>;
+                               regulator-max-microvolt = <2800000>;
+                               qcom,comsumer-supplies = "rt5025-ldo3", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo4: regulator_7 {
+                               regulator-name = "rt5025-ldo4";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               qcom,comsumer-supplies = "rt5025-ldo4", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo5: regulator_8 {
+                               regulator-name = "rt5025-ldo5";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               qcom,comsumer-supplies = "rt5025-ldo5", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+                       rt5025_ldo6: regulator_9 {
+                               regulator-name = "rt5025-ldo6";
+                               regulator-min-microvolt = <330000>;
+                               regulator-max-microvolt = <3300000>;
+                               qcom,comsumer-supplies = "rt5025-ldo6", "";
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+
+       rt5025-irq {
+                               compatible = "rt,rt5025-irq";
+                               rt,irq-gpio = <&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>;
+       };
+};
+
 /include/ "rk818.dtsi"
 &rk818 {
        gpios =<&gpio1 GPIO_B1 GPIO_ACTIVE_HIGH>,<&gpio1 GPIO_A1 GPIO_ACTIVE_LOW>;
diff --git a/arch/arm/boot/dts/rt5025.dtsi b/arch/arm/boot/dts/rt5025.dtsi
new file mode 100755 (executable)
index 0000000..d78f0dc
--- /dev/null
@@ -0,0 +1,113 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rt5025 {
+       compatible = "rt,rt5025";
+//     reg = <0x35>;
+
+                       rt5025_dcdc1: regulator_0 {
+                               compatible = "rt,rt5025-dcdc1";
+                               cell-index = <0>;
+                               rt,ramp_sel = <0x00>;
+                               rt,allow_mode_mask;
+                       };
+
+                       rt5025_dcdc2: regulator_1 {
+                               compatible = "rt,rt5025-dcdc2";
+                               cell-index = <1>;
+                               rt,ramp_sel = <0x00>;
+                               rt,allow_mode_mask;
+                       };
+
+                       rt5025_dcdc3: regulator_2 {
+                               compatible = "rt,rt5025-dcdc3";
+                               cell-index = <2>;
+                               rt,ramp_sel = <0x00>;
+                               rt,allow_mode_mask;
+                       };
+
+                       rt5025_dcdc4: regulator_3 {
+                               compatible = "rt,rt5025-dcdc4";
+                               cell-index = <3>;
+                       };
+
+                       rt5025_ldo1: regulator_4 {
+                               compatible = "rt,rt5025-ldo1";
+                               cell-index = <4>;
+                       };
+
+                       rt5025_ldo2: regulator_5 {
+                               compatible = "rt,rt5025-ldo2";
+                               cell-index = <5>;
+                       };
+
+                       rt5025_ldo3: regulator_6 {
+                               compatible = "rt,rt5025-ldo3";
+                               cell-index = <6>;
+                       };
+
+                       rt5025_ldo4: regulator_7 {
+                               compatible = "rt,rt5025-ldo4";
+                               cell-index = <7>;
+                       };
+
+                       rt5025_ldo5: regulator_8 {
+                               compatible = "rt,rt5025-ldo5";
+                               cell-index = <8>;
+                       };
+
+                       rt5025_ldo6: regulator_9 {
+                               compatible = "rt,rt5025-ldo6";
+                               cell-index = <9>;
+                       };
+                       
+                       rt5025-charger {
+                               compatible = "rt,rt5025-charger";
+                               rt,te_en;
+                               //rt,screenon_adjust;
+                               rt,iprec = <0x00>;
+                               rt,ieoc = <0x00>;
+                               rt,vprec = <0x05>;
+                               rt,vdpm = <0x02>;
+                               rt,chg_volt = <4200>;
+                               rt,acchg_icc = <2000>;
+                               rt,usbtachg_icc = <2000>;
+                               rt,usbchg_icc = <500>;
+                               rt,screenon_icc = <500>;
+                               rt,temp = <0 150 500 600>;
+                               rt,temp_scalar = <0x30 0x2b 0x28 0x22 0x15 0x10 0x10 0x0d>;
+                       };
+
+                       rt5025-battery {
+                               compatible = "rt,rt5025-battery";
+                       };
+
+                       rt5025_gpio: rt5025-gpio {
+                               compatible = "rt,rt5025-gpio";
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               rt,ngpio = <3>;
+                       };
+                       rt5025-misc {
+                               compatible = "rt,rt5025-misc";
+                               rt,vsyslv = <0x02>;
+                               rt,shdnlpress_time = <0x01>;
+                               rt,startlpress_time = <0x00>;
+                               rt,vsyslv_enshdn;
+                               rt,system-power-controller;
+
+                       };
+
+                       rt5025-debug {
+                               compatible = "rt,rt5025-debug";
+                       };
+};
index 573c449c49b9138a69f8aaf9a999e8a41898d2e1..6dc75d5c2ed14205bba601a13a014238bb8b8960 100644 (file)
@@ -209,6 +209,13 @@ config GPIO_RCAR
        help
          Say yes here to support GPIO on Renesas R-Car SoCs.
 
+config GPIO_RT5025
+       bool "Richtek RT5025 GPIO support"
+       depends on MFD_RT5025
+       default n
+       help
+         This is the gpio driver for RT5025 PMIC.
+
 config GPIO_SPEAR_SPICS
        bool "ST SPEAr13xx SPI Chip Select as GPIO support"
        depends on PLAT_SPEAR
index 0cb2d656ad16b96663d921cb2b2ee910d944209f..39585cb14392c69578fc93a648ab017d64d3f135 100644 (file)
@@ -87,3 +87,4 @@ obj-$(CONFIG_GPIO_WM831X)     += gpio-wm831x.o
 obj-$(CONFIG_GPIO_WM8350)      += gpio-wm8350.o
 obj-$(CONFIG_GPIO_WM8994)      += gpio-wm8994.o
 obj-$(CONFIG_GPIO_XILINX)      += gpio-xilinx.o
+obj-$(CONFIG_GPIO_RT5025)      += gpio-rt5025.o
diff --git a/drivers/gpio/gpio-rt5025.c b/drivers/gpio/gpio-rt5025.c
new file mode 100755 (executable)
index 0000000..f033b32
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ *  drivers/gpio/rt5025-gpio.c
+ *  Driver foo Richtek RT5025 PMIC GPIO
+ *
+ *  Copyright (C) 2014 Richtek Technologh Corp.
+ *  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; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <linux/mfd/rt5025.h>
+#include <linux/mfd/rt5025-gpio.h>
+
+struct rt5025_gpio_info {
+       struct i2c_client *i2c;
+       unsigned gpio_base;
+       unsigned irq_base;
+       int ngpio;
+       struct gpio_chip gpio_chip;
+};
+
+static inline int find_rt5025_gpioreg(unsigned off, int *gpio_reg)
+{
+       int ret = 0;
+
+       switch (off) {
+       case 0:
+       case 1:
+       case 2:
+               *gpio_reg = RT5025_REG_GPIO0 + off;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int rt5025_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
+       int gpio_reg = 0;
+       int ret = 0;
+
+       ret = find_rt5025_gpioreg(offset , &gpio_reg);
+       if (ret < 0) {
+               dev_err(chip->dev, "not a valid gpio index\n");
+               return ret;
+       }
+
+       ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRMASK);
+       if (ret < 0) {
+               dev_err(chip->dev, "set gpio input fail\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rt5025_gpio_direction_output(struct gpio_chip *chip,
+       unsigned offset, int value)
+{
+       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
+       int gpio_reg = 0;
+       int ret = 0;
+
+       ret = find_rt5025_gpioreg(offset, &gpio_reg);
+       if (ret < 0) {
+               dev_err(chip->dev, "not a valid gpio index\n");
+               return ret;
+       }
+
+       ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRSHIFT);
+       if (ret < 0) {
+               dev_err(chip->dev, "clr gpio direction fail\n");
+               return ret;
+       }
+
+       ret = rt5025_set_bits(gi->i2c, gpio_reg,
+               RT5025_GPIO_OUTPUT<<RT5025_GPIO_DIRSHIFT);
+       if (ret < 0) {
+               dev_err(chip->dev, "set gpio output dir fail\n");
+               return ret;
+       }
+
+       if (value)
+               ret = rt5025_set_bits(gi->i2c, gpio_reg,
+               RT5025_GPIO_OVALUEMASK);
+       else
+               ret = rt5025_clr_bits(gi->i2c, gpio_reg,
+               RT5025_GPIO_OVALUEMASK);
+
+       if (ret < 0) {
+               dev_err(chip->dev, "set gpio output value fail\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int rt5025_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
+       int gpio_reg = 0;
+       int ret = 0;
+
+       ret = find_rt5025_gpioreg(offset, &gpio_reg);
+       if (ret < 0) {
+               dev_err(chip->dev, "not a valid gpio index\n");
+               return ret;
+       }
+
+       ret = rt5025_reg_read(gi->i2c, gpio_reg);
+       if (ret < 0) {
+               dev_err(chip->dev, "read gpio register fail\n");
+               return ret;
+       }
+
+       return (ret&RT5025_GPIO_IVALUEMASK)?1 : 0;
+}
+
+static void rt5025_gpio_set_value(struct gpio_chip *chip,
+       unsigned offset, int value)
+{
+       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
+       int gpio_reg = 0;
+       int ret = 0;
+
+       ret = find_rt5025_gpioreg(offset, &gpio_reg);
+       if (ret < 0) {
+               dev_err(chip->dev, "not a valid gpio index\n");
+               return;
+       }
+
+       if (value)
+               ret = rt5025_set_bits(gi->i2c, gpio_reg,
+               RT5025_GPIO_OVALUEMASK);
+       else
+               ret = rt5025_clr_bits(gi->i2c, gpio_reg,
+               RT5025_GPIO_OVALUEMASK);
+
+       if (ret < 0)
+               dev_err(chip->dev, "read gpio register fail\n");
+}
+
+static int rt_parse_dt(struct rt5025_gpio_info *gi, struct device *dev)
+{
+       #ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+
+       of_property_read_u32(np, "rt,ngpio", &gi->ngpio);
+       #endif /* #ifdef CONFIG_OF */
+       return 0;
+}
+
+static int rt_parse_pdata(struct rt5025_gpio_info *gi, struct device *dev)
+{
+       struct rt5025_gpio_data *gpio_pdata = dev->platform_data;
+
+       gi->ngpio = gpio_pdata->ngpio;
+       return 0;
+}
+
+static int rt5025_gpio_probe(struct platform_device *pdev)
+{
+       struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct rt5025_platform_data *pdata = (pdev->dev.parent)->platform_data;
+       struct rt5025_gpio_info *gi;
+       bool use_dt = pdev->dev.of_node;
+       int rc = 0;
+
+       gi = devm_kzalloc(&pdev->dev, sizeof(*gi), GFP_KERNEL);
+       if (!gi)
+               return -ENOMEM;
+
+
+       gi->i2c = chip->i2c;
+       if (use_dt) {
+               rt_parse_dt(gi, &pdev->dev);
+       } else {
+               if (!pdata) {
+                       rc = -EINVAL;
+                       goto out_dev;
+               }
+               pdev->dev.platform_data = pdata->gpio_pdata;
+               rt_parse_pdata(gi, &pdev->dev);
+       }
+
+       gi->gpio_chip.direction_input  = rt5025_gpio_direction_input;
+       gi->gpio_chip.direction_output = rt5025_gpio_direction_output;
+       gi->gpio_chip.get = rt5025_gpio_get_value;
+       gi->gpio_chip.set = rt5025_gpio_set_value;
+       gi->gpio_chip.can_sleep = 0;
+
+       gi->gpio_chip.base = -1;
+       gi->gpio_chip.ngpio = gi->ngpio;
+       gi->gpio_chip.label = pdev->name;
+       gi->gpio_chip.dev = &pdev->dev;
+       gi->gpio_chip.owner = THIS_MODULE;
+
+       rc = gpiochip_add(&gi->gpio_chip);
+       if (rc)
+               goto out_dev;
+
+       platform_set_drvdata(pdev, gi);
+       dev_info(&pdev->dev, "driver successfully loaded\n");
+       return rc;
+out_dev:
+       return rc;
+}
+
+static int rt5025_gpio_remove(struct platform_device *pdev)
+{
+       int rc = 0;
+       struct rt5025_gpio_info *gi = platform_get_drvdata(pdev);
+
+       rc = gpiochip_remove(&gi->gpio_chip);
+       dev_info(&pdev->dev, "\n");
+       return 0;
+}
+
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-gpio",},
+       {},
+};
+
+static struct platform_driver rt5025_gpio_driver = {
+       .driver = {
+               .name = RT5025_DEV_NAME "-gpio",
+               .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
+       },
+       .probe = rt5025_gpio_probe,
+       .remove = rt5025_gpio_remove,
+};
+
+static int rt5025_gpio_init(void)
+{
+       return platform_driver_register(&rt5025_gpio_driver);
+}
+fs_initcall_sync(rt5025_gpio_init);
+
+static void rt5025_gpio_exit(void)
+{
+       platform_driver_unregister(&rt5025_gpio_driver);
+}
+module_exit(rt5025_gpio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("GPIO driver for RT5025");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-gpio");
+MODULE_VERSION(RT5025_DRV_VER);
diff --git a/drivers/gpio/rt5025-gpio.c b/drivers/gpio/rt5025-gpio.c
deleted file mode 100755 (executable)
index 97bebcd..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- *  drivers/gpio/rt5025-gpio.c
- *  Driver foo Richtek RT5025 PMIC GPIO
- *
- *  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.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/i2c.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-
-#include <linux/mfd/rt5025.h>
-#include <linux/mfd/rt5025-gpio.h>
-
-struct rt5025_gpio_info {
-       struct i2c_client *i2c;
-       unsigned gpio_base;
-       unsigned irq_base;
-       struct gpio_chip gpio_chip;
-};
-
-static inline int find_rt5025_gpioreg(unsigned off, int *gpio_reg)
-{
-       int ret = 0;
-       switch (off)
-       {
-               case 0:
-               case 1:
-               case 2:
-                       *gpio_reg = RT5025_REG_GPIO0 + off;
-                       break;
-               default:
-                       ret = -EINVAL;
-       }
-       return ret;
-}
-
-static int rt5025_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
-       int gpio_reg = 0;
-       int ret = 0;
-       
-       ret = find_rt5025_gpioreg(offset , &gpio_reg);
-       if (ret < 0)
-       {
-               dev_err(chip->dev, "not a valid gpio index\n");
-               return ret;
-       }
-
-       ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRMASK);
-       if (ret<0)
-       {
-               dev_err(chip->dev, "set gpio input fail\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int rt5025_gpio_direction_output(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
-       int gpio_reg = 0;
-       int ret = 0;
-       
-       ret = find_rt5025_gpioreg(offset, &gpio_reg);
-       if (ret < 0)
-       {
-               dev_err(chip->dev, "not a valid gpio index\n");
-               return ret;
-       }
-       
-       ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_DIRSHIFT);
-       if (ret<0)
-       {
-               dev_err(chip->dev, "clr gpio direction fail\n");
-               return ret;
-       }
-
-       ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OUTPUT<<RT5025_GPIO_DIRSHIFT);
-       if (ret<0)
-       {
-               dev_err(chip->dev, "set gpio output dir fail\n");
-               return ret;
-       }
-
-       if (value)
-               ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
-       else
-               ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
-
-       if (ret<0)
-       {
-               dev_err(chip->dev, "set gpio output value fail\n");
-               return ret;
-       }
-
-       return 0;
-}
-
-static int rt5025_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
-       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
-       int gpio_reg = 0;
-       int ret = 0;
-       
-       ret = find_rt5025_gpioreg(offset, &gpio_reg);
-       if (ret < 0)
-       {
-               dev_err(chip->dev, "not a valid gpio index\n");
-               return ret;
-       }
-       
-       ret = rt5025_reg_read(gi->i2c, gpio_reg);
-       if (ret<0)
-       {
-               dev_err(chip->dev, "read gpio register fail\n");
-               return ret;
-       }
-
-       return (ret&RT5025_GPIO_IVALUEMASK)?1:0;
-}
-
-static void rt5025_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
-{
-       struct rt5025_gpio_info *gi = dev_get_drvdata(chip->dev);
-       int gpio_reg = 0;
-       int ret = 0;
-       
-       ret = find_rt5025_gpioreg(offset, &gpio_reg);
-       if (ret < 0)
-       {
-               dev_err(chip->dev, "not a valid gpio index\n");
-               return;
-       }
-
-       if (value)
-               ret = rt5025_set_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
-       else
-               ret = rt5025_clr_bits(gi->i2c, gpio_reg, RT5025_GPIO_OVALUEMASK);
-
-       if (ret<0)
-       {
-               dev_err(chip->dev, "read gpio register fail\n");
-       }
-}
-
-static int __devinit rt5025_gpio_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_gpio_info *gi;
-       int ret = 0;
-
-       gi = kzalloc(sizeof(*gi), GFP_KERNEL);
-       if (!gi)
-               return -ENOMEM;
-
-       gi->i2c = chip->i2c;
-       gi->gpio_base = pdata->gpio_data->gpio_base;
-       gi->irq_base = pdata->gpio_data->irq_base;
-
-       gi->gpio_chip.direction_input  = rt5025_gpio_direction_input;
-       gi->gpio_chip.direction_output = rt5025_gpio_direction_output;
-       gi->gpio_chip.get = rt5025_gpio_get_value;
-       gi->gpio_chip.set = rt5025_gpio_set_value;
-       gi->gpio_chip.can_sleep = 0;
-
-       gi->gpio_chip.base = gi->gpio_base;
-       gi->gpio_chip.ngpio = RT5025_GPIO_NR;
-       gi->gpio_chip.label = pdev->name;
-       gi->gpio_chip.dev = &pdev->dev;
-       gi->gpio_chip.owner = THIS_MODULE;
-
-       ret = gpiochip_add(&gi->gpio_chip);
-       if (ret)
-               goto out_dev;
-               
-       platform_set_drvdata(pdev, gi);
-       return ret;
-out_dev:
-       kfree(gi);
-       return ret;
-}
-
-static int __devexit rt5025_gpio_remove(struct platform_device *pdev)
-{
-       int ret;
-       struct rt5025_gpio_info *gi = platform_get_drvdata(pdev);
-
-       ret = gpiochip_remove(&gi->gpio_chip);
-       kfree(gi);
-
-       platform_set_drvdata(pdev, NULL);
-       return 0;
-}
-
-static struct platform_driver rt5025_gpio_driver = 
-{
-       .driver = {
-               .name = RT5025_DEVICE_NAME "-gpio",
-               .owner = THIS_MODULE,
-       },
-       .probe = rt5025_gpio_probe,
-       .remove = __devexit_p(rt5025_gpio_remove),
-};
-
-static int __init rt5025_gpio_init(void)
-{
-       return platform_driver_register(&rt5025_gpio_driver);
-}
-subsys_initcall_sync(rt5025_gpio_init);
-
-static void __exit rt5025_gpio_exit(void)
-{
-       platform_driver_unregister(&rt5025_gpio_driver);
-}
-module_exit(rt5025_gpio_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
-MODULE_DESCRIPTION("GPIO driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-gpio");
-MODULE_VERSION(RT5025_DRV_VER);
index 8fd1c29eccfa4e281b5cfefa8645b3b8c0e2a7bc..d57c5cfa7c59206281b64e569bc7ff43dea8e546 100755 (executable)
@@ -169,6 +169,42 @@ config MFD_MC13XXX_I2C
        help
          Select this if your MC13xxx is connected via an I2C bus.
 
+config MFD_RT5025
+       bool "RT5025 PMIC Chip Core driver"
+       depends on I2C
+       select MFD_CORE
+       default n
+       help
+         Enable RT5025 core driver.
+
+config MISC_RT5025
+       bool "RT5025 PMIC chip misc configuration"
+       depends on MFD_RT5025
+       default n
+       help
+         Enable RT5025 Misc configuration.
+
+config IRQ_RT5025
+       bool "RT5025_PMIC chip irq driver"
+       depends on MFD_RT5025
+       default n
+       help
+         Enable RT5025 IRQ configuration and interrupt.
+
+config DEBUG_RT5025
+       bool "RT5025 PMIC Chip Core Debug"
+       depends on MFD_RT5025 && DEBUG_FS
+       default n
+       help
+         Enable RT5025 core debug driver.
+
+config MFD_RT_SHOW_INFO
+       bool "RT5025 PMIC Debug log Flag"
+       depends on MFD_RT5025
+       default n
+       help
+         Enable the RT5025 PMIC debug log.
+
 config HTC_EGPIO
        bool "HTC EGPIO support"
        depends on GENERIC_HARDIRQS && GPIOLIB && ARM
index 160e4d908873e7de1bf906e4f37e4f8118e4a37a..1a69560d8dcbc53377191a265bff1d0db866d307 100755 (executable)
@@ -55,6 +55,11 @@ obj-$(CONFIG_MFD_WM8350)     += wm8350.o
 obj-$(CONFIG_MFD_WM8350_I2C)   += wm8350-i2c.o
 obj-$(CONFIG_MFD_WM8994)       += wm8994-core.o wm8994-irq.o wm8994-regmap.o
 
+obj-$(CONFIG_MFD_RT5025)       += rt5025-i2c.o rt5025-core.o
+obj-$(CONFIG_MISC_RT5025)      += rt5025-misc.o
+obj-$(CONFIG_IRQ_RT5025)       += rt5025-irq.o
+obj-$(CONFIG_DEBUG_RT5025)     += rt5025-debug.o
+
 obj-$(CONFIG_TPS6105X)         += tps6105x.o
 obj-$(CONFIG_TPS65010)         += tps65010.o
 obj-$(CONFIG_TPS6507X)         += tps6507x.o
old mode 100644 (file)
new mode 100755 (executable)
index 245c1c0..02b46a4
@@ -2,12 +2,13 @@
  *  drivers/mfd/rt5025-core.c
  *  Driver for Richtek RT5025 Core PMIC
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2014 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/i2c.h>
 #include <linux/mfd/core.h>
-
 #include <linux/mfd/rt5025.h>
 
 #ifdef CONFIG_REGULATOR_RT5025
-#define RT5025_VR_DEVS(_id)                                            \
+#ifdef CONFIG_OF
+#define RT5025_BUCKVR_DEVS(_id, _idx)                                  \
 {                                                                      \
-       .name           = RT5025_DEVICE_NAME "-regulator",                              \
+       .name           = RT5025_DEV_NAME "-regulator",         \
        .num_resources  = 0,                                            \
+       .of_compatible  = "rt," RT5025_DEV_NAME "-dcdc" #_idx ,         \
        .id             = RT5025_ID_##_id,                              \
 }
 
+#define RT5025_LDOVR_DEVS(_id, _idx)                                   \
+{                                                                      \
+       .name           = RT5025_DEV_NAME "-regulator",         \
+       .num_resources  = 0,                                            \
+       .of_compatible  = "rt," RT5025_DEV_NAME "-ldo" #_idx ,  \
+       .id             = RT5025_ID_##_id,                              \
+}
+#else
+#define RT5025_BUCKVR_DEVS(_id, _idx)                                  \
+{                                                                      \
+       .name           = RT5025_DEV_NAME "-regulator",         \
+       .num_resources  = 0,                                            \
+       .id             = RT5025_ID_##_id,                              \
+}
+
+#define RT5025_LDOVR_DEVS(_id, _idx)                                   \
+{                                                                      \
+       .name           = RT5025_DEV_NAME "-regulator",         \
+       .num_resources  = 0,                                            \
+       .id             = RT5025_ID_##_id,                              \
+}
+#endif /* #ifdef CONFIG_OF */
 static struct mfd_cell regulator_devs[] = {
-       RT5025_VR_DEVS(DCDC1),
-       RT5025_VR_DEVS(DCDC2),
-       RT5025_VR_DEVS(DCDC3),
-       RT5025_VR_DEVS(DCDC4),
-       RT5025_VR_DEVS(LDO1),
-       RT5025_VR_DEVS(LDO2),
-       RT5025_VR_DEVS(LDO3),
-       RT5025_VR_DEVS(LDO4),
-       RT5025_VR_DEVS(LDO5),
-       RT5025_VR_DEVS(LDO6),
+       RT5025_BUCKVR_DEVS(DCDC1, 1),
+       RT5025_BUCKVR_DEVS(DCDC2, 2),
+       RT5025_BUCKVR_DEVS(DCDC3, 3),
+       RT5025_BUCKVR_DEVS(DCDC4, 4),
+       RT5025_LDOVR_DEVS(LDO1,   1),
+       RT5025_LDOVR_DEVS(LDO2,   2),
+       RT5025_LDOVR_DEVS(LDO3,   3),
+       RT5025_LDOVR_DEVS(LDO4,   4),
+       RT5025_LDOVR_DEVS(LDO5,   5),
+       RT5025_LDOVR_DEVS(LDO6,   6),
 };
-#endif /* CONFIG_REGULATOR_RT5025 */
+#endif /* #ifdef CONFIG_REGULATOR_RT5025 */
 
-#ifdef CONFIG_POWER_RT5025
-static struct mfd_cell power_devs[] = {
-{
-       .name = RT5025_DEVICE_NAME "-power",
-       .id = -1,
-       .num_resources = 0,
-},
+#ifdef CONFIG_CHARGER_RT5025
+static struct mfd_cell chg_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-swjeita",
+       .name = RT5025_DEV_NAME "-charger",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-charger" ,
+#endif /*#ifdef CONFIG_OF */
 },
+};
+#endif /* #ifdef CONFIG_CHARGER_RT5025 */
+
+#ifdef CONFIG_BATTERY_RT5025
+static struct mfd_cell fg_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-battery",
+       .name = RT5025_DEV_NAME "-battery",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-battery" ,
+#endif /*#ifdef CONFIG_OF */
 },
 };
-#endif /* CONFIG_POWER_RT5025 */
+#endif /* #ifdef CONFIG_BATTERY_RT5025 */
 
 #ifdef CONFIG_GPIO_RT5025
 static struct mfd_cell gpio_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-gpio",
+       .name = RT5025_DEV_NAME "-gpio",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-gpio" ,
+#endif /*#ifdef CONFIG_OF */
 },
 };
-#endif /* CONFIG_GPIO_RT5025 */
+#endif /* #ifdef CONFIG_GPIO_RT5025 */
 
-#ifdef CONFIG_MFD_RT5025_MISC
+#ifdef CONFIG_MISC_RT5025
 static struct mfd_cell misc_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-misc",
+       .name = RT5025_DEV_NAME "-misc",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-misc" ,
+#endif /*#ifdef CONFIG_OF */
 },
 };
-#endif /* CONFIG_MFD_RT5025_MISC */
+#endif /* #ifdef CONFIG_MISC_RT5025 */
 
-#ifdef CONFIG_MFD_RT5025_IRQ
+#ifdef CONFIG_IRQ_RT5025
 static struct mfd_cell irq_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-irq",
+       .name = RT5025_DEV_NAME "-irq",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-irq" ,
+#endif /*#ifdef CONFIG_OF */
 },
 };
-#endif /* CONFIG_MFD_RT5025_IRQ */
+#endif /* #ifdef CONFIG_IRQ_RT5025 */
 
-#ifdef CONFIG_MFD_RT5025_DEBUG
+#ifdef CONFIG_DEBUG_RT5025
 static struct mfd_cell debug_devs[] = {
 {
-       .name = RT5025_DEVICE_NAME "-debug",
+       .name = RT5025_DEV_NAME "-debug",
        .id = -1,
        .num_resources = 0,
+#ifdef CONFIG_OF
+       .of_compatible  = "rt," RT5025_DEV_NAME "-debug" ,
+#endif /*#ifdef CONFIG_OF */
 },
 };
-#endif /* CONFIG_MFD_RT5025_DEBUG */
+#endif /* #ifdef CONFIG_DEBUG_RT5025 */
 
-int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_data *pdata)
+int rt5025_core_init(struct rt5025_chip *chip,
+       struct rt5025_platform_data *pdata)
 {
        int ret = 0;
+       bool use_dt = chip->dev->of_node;
 
        RTINFO("Start to initialize all device\n");
 
        #ifdef CONFIG_REGULATOR_RT5025
-       if (pdata && pdata->regulator[0]) {
+       if (use_dt || (pdata && pdata->regulator[0])) {
                RTINFO("mfd add regulators dev\n");
-               #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
                ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
                                      ARRAY_SIZE(regulator_devs),
                                      NULL, 0, NULL);
@@ -117,24 +161,43 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
                                      ARRAY_SIZE(regulator_devs),
                                      NULL, 0);
-               #endif /* LINUX_VERSION_CODE>=KERNL_VERSION(3,6,0) */
+               #endif /* LINUX_VERSION_CODE >= KERNL_VERSION(3,6,0) */
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add regulator subdev\n");
                        goto out_dev;
                }
        }
-       #endif /* CONFIG_REGULATOR_RT5025 */
-
-       #ifdef CONFIG_POWER_RT5025
-       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],
-                                       ARRAY_SIZE(power_devs),
-                                       NULL, 0,NULL);
+       #endif /* #ifdef CONFIG_REGULATOR_RT5025 */
+
+       #ifdef CONFIG_CHARGER_RT5025
+       if (use_dt || (pdata && pdata->chg_pdata)) {
+           RTINFO("mfd add charger dev\n");
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+               ret = mfd_add_devices(chip->dev, 0, &chg_devs[0],
+                                       ARRAY_SIZE(chg_devs),
+                                       NULL, 0, NULL);
+               #else
+               ret = mfd_add_devices(chip->dev, 0, &chg_devs[0],
+                                       ARRAY_SIZE(chg_devs),
+                                       NULL, 0);
+               #endif
+               if (ret < 0) {
+                       dev_err(chip->dev, "Failed to add power supply subdev\n");
+                       goto out_dev;
+               }
+       }
+       #endif /* #ifdef CONFIG_CHARGER_RT5025 */
+
+       #ifdef CONFIG_BATTERY_RT5025
+       if (use_dt || (pdata)) {
+           RTINFO("mfd add fuelgauge dev\n");
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
+               ret = mfd_add_devices(chip->dev, 0, &fg_devs[0],
+                                       ARRAY_SIZE(fg_devs),
+                                       NULL, 0, NULL);
                #else
-               ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
-                                       ARRAY_SIZE(power_devs),
+               ret = mfd_add_devices(chip->dev, 0, &fg_devs[0],
+                                       ARRAY_SIZE(fg_devs),
                                        NULL, 0);
                #endif
                if (ret < 0) {
@@ -143,13 +206,13 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                        goto out_dev;
                }
        }
-       #endif /* CONFIG_MFD_RT5025 */
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
 
-       //Initialize the RT5025_GPIO
+       /*Initialize the RT5025_GPIO*/
        #ifdef CONFIG_GPIO_RT5025
-       if (pdata && pdata->gpio_data) {
+       if (use_dt || (pdata && pdata->gpio_pdata)) {
                RTINFO("mfd add gpios dev\n");
-               #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
                ret = mfd_add_devices(chip->dev, 0, &gpio_devs[0],
                                      ARRAY_SIZE(gpio_devs),
                                      NULL, 0, NULL);
@@ -163,12 +226,12 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                        goto out_dev;
                }
        }
-       #endif /* CONFIG_GPIO_RT5025 */
+       #endif /* #ifdef CONFIG_GPIO_RT5025 */
 
-       #ifdef CONFIG_MFD_RT5025_MISC
-       if (pdata && pdata->misc_data) {
+       #ifdef CONFIG_MISC_RT5025
+       if (use_dt || (pdata && pdata->misc_pdata)) {
                RTINFO("mfd add misc dev\n");
-               #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
                ret = mfd_add_devices(chip->dev, 0, &misc_devs[0],
                                      ARRAY_SIZE(misc_devs),
                                      NULL, 0, NULL);
@@ -182,12 +245,12 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                        goto out_dev;
                }
        }
-       #endif /* CONFIG_MFD_RT5025_MISC */
+       #endif /* #ifdef CONFIG_MISC_RT5025 */
 
-       #ifdef CONFIG_MFD_RT5025_IRQ
-       if (pdata && pdata->irq_data) {
+       #ifdef CONFIG_IRQ_RT5025
+       if (use_dt || (pdata && pdata->irq_pdata)) {
                RTINFO("mfd add irq dev\n");
-               #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
+               #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
                ret = mfd_add_devices(chip->dev, 0, &irq_devs[0],
                                      ARRAY_SIZE(irq_devs),
                                      NULL, 0, NULL);
@@ -201,11 +264,11 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                        goto out_dev;
                }
        }
-       #endif /* CONFIG_MFD_RT5025_IRQ */
+       #endif /* #ifdef CONFIG_IRQ_RT5025 */
 
-       #ifdef CONFIG_MFD_RT5025_DEBUG
+       #ifdef CONFIG_DEBUG_RT5025
        RTINFO("mfd add debug dev\n");
-       #if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
+       #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
        ret = mfd_add_devices(chip->dev, 0, &debug_devs[0],
                              ARRAY_SIZE(debug_devs),
                              NULL, 0, NULL);
@@ -218,7 +281,7 @@ int __devinit rt5025_core_init(struct rt5025_chip *chip, struct rt5025_platform_
                dev_err(chip->dev, "Failed to add debug subdev\n");
                goto out_dev;
        }
-       #endif /* CONFIG_MFD_RT5025_DEBUG */
+       #endif /* CONFIG_DEBUG_RT5025 */
 
        RTINFO("Initialize all device successfully\n");
        return ret;
@@ -228,7 +291,7 @@ out_dev:
 }
 EXPORT_SYMBOL(rt5025_core_init);
 
-int __devexit rt5025_core_deinit(struct rt5025_chip *chip)
+int rt5025_core_deinit(struct rt5025_chip *chip)
 {
        mfd_remove_devices(chip->dev);
        return 0;
old mode 100644 (file)
new mode 100755 (executable)
index 5f6d816..d899fd9
@@ -2,12 +2,13 @@
  *  drivers/mfd/rt5025-debug.c
  *  Driver foo Richtek RT5025 PMIC Debug
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2013 Richtek Technologh Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
-
-#include <linux/uaccess.h>
 #include <linux/debugfs.h>
-#include <linux/string.h>
+#include <linux/uaccess.h>
 
 #include <linux/mfd/rt5025.h>
 
 struct rt5025_debug_info {
        struct i2c_client *i2c;
+       struct device *dev;
+       unsigned char reg_addr;
+       unsigned char reg_data;
 };
 
-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 struct dentry *debugfs_reset_b;
+struct rt_debug_st {
+       void *info;
+       int id;
+};
 
-static unsigned char read_data[10];
+enum {
+       RT5025_DBG_REG,
+       RT5025_DBG_DATA,
+       RT5025_DBG_REGS,
+       RT5025_DBG_MAX
+};
+
+static struct dentry *debugfs_rt_dent;
+static struct dentry *debugfs_file[RT5025_DBG_MAX];
+static struct rt_debug_st rtdbg_data[RT5025_DBG_MAX];
 
 static int reg_debug_open(struct inode *inode, struct file *file)
 {
@@ -60,37 +68,60 @@ static int get_parameters(char *buf, long int *param1, int num_of_par)
                                return -EINVAL;
 
                        token = strsep(&buf, " ");
-                       }
-               else
+               } else {
                        return -EINVAL;
+               }
        }
        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 *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]);
+       struct rt_debug_st *st = filp->private_data;
+       struct rt5025_debug_info *di = st->info;
+       char lbuf[1000];
+       int i = 0, j = 0;
+
+       lbuf[0] = '\0';
+       switch (st->id) {
+       case RT5025_DBG_REG:
+               snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_addr);
+               break;
+       case RT5025_DBG_DATA:
+               di->reg_data = (unsigned char)rt5025_reg_read(di->i2c,
+                       di->reg_addr);
+               snprintf(lbuf, sizeof(lbuf), "0x%x\n", di->reg_data);
+               break;
+       case RT5025_DBG_REGS:
+               for (i = RT5025_REG_RANGE1START;
+                       i <= RT5025_REG_RANGE1END; i++)
+                       j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
+                               rt5025_reg_read(di->i2c, i));
+               for (i = RT5025_REG_RANGE2START;
+                       i <= RT5025_REG_RANGE2END; i++)
+                       j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
+                               rt5025_reg_read(di->i2c, i));
+               for (i = RT5025_REG_RANGE3START;
+                       i <= RT5025_REG_RANGE3END; i++)
+                       j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
+                               rt5025_reg_read(di->i2c, i));
+               for (i = RT5025_REG_RANGE4START;
+                       i <= RT5025_REG_RANGE4END; i++)
+                       j += sprintf(lbuf+j, "0x%02x:%02x\n", i, \
+                               rt5025_reg_read(di->i2c, i));
+               break;
+       default:
+               return -EINVAL;
        }
-       else
-               snprintf(lbuf, sizeof(lbuf), "0x%02x\n", read_data[0]);
        return simple_read_from_buffer(ubuf, count, ppos, lbuf, strlen(lbuf));
 }
 
 static ssize_t reg_debug_write(struct file *filp,
        const char __user *ubuf, size_t cnt, loff_t *ppos)
 {
-       char *access_str = filp->private_data;
+       struct rt_debug_st *st = filp->private_data;
+       struct rt5025_debug_info *di = st->info;
        char lbuf[32];
        int rc;
        long int param[5];
@@ -104,56 +135,37 @@ static ssize_t reg_debug_write(struct file *filp,
 
        lbuf[cnt] = '\0';
 
-       if (!strcmp(access_str, "poke")) {
-               /* write */
-               rc = get_parameters(lbuf, param, 2);
-               if ((param[0] <= 0xFF) && (param[1] <= 0xFF) && (rc == 0))
-               {
-                       rt5025_reg_write(client, param[0], (unsigned char)param[1]);
-               }
-               else
-                       rc = -EINVAL;
-       } else if (!strcmp(access_str, "peek")) {
-               /* read */
+       switch (st->id) {
+       case RT5025_DBG_REG:
                rc = get_parameters(lbuf, param, 1);
-               if ((param[0] <= 0xFF) && (rc == 0))
-               {
-                       read_data[0] = rt5025_reg_read(client, param[0]);
+               if ((param[0] < RT5025_REG_MAX) && (rc == 0)) {
+                       if ((param[0] >= RT5025_REG_RANGE1START && param[0]
+                               <= RT5025_REG_RANGE1END) || \
+                               (param[0] >= RT5025_REG_RANGE2START && param[0]
+                               <= RT5025_REG_RANGE2END) || \
+                               (param[0] >= RT5025_REG_RANGE3START && param[0]
+                               <= RT5025_REG_RANGE3END) || \
+                               (param[0] >= RT5025_REG_RANGE4START && param[0]
+                               <= RT5025_REG_RANGE4END))
+                               di->reg_addr = (unsigned char)param[0];
+                       else
+                               rc = -EINVAL;
+               } else {
+                               rc = -EINVAL;
                }
-               else
-                       rc = -EINVAL;
-       } else if (!strcmp(access_str, "regs")) {
-               /* read */
+               break;
+       case RT5025_DBG_DATA:
                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]);
-               }
+               if ((param[0] <= 0xff) && (rc == 0))
+                       rt5025_reg_write(di->i2c, di->reg_addr, param[0]);
                else
                        rc = -EINVAL;
-       } else if (!strcmp(access_str, "reset_b")) {
-               /* read */
-               rc = get_parameters(lbuf, param, 1);
-               if (param[0] == 1 && rc == 0)
-               {
-                       memset(lbuf, 0, 15);
-                       rt5025_reg_block_write(client, 0x21, 15, lbuf);
-               }
+               break;
+       default:
+               return -EINVAL;
        }
-
        if (rc == 0)
                rc = cnt;
-
        return rc;
 }
 
@@ -163,78 +175,84 @@ static const struct file_operations reg_debug_ops = {
        .read = reg_debug_read
 };
 
-static int __devinit rt5025_debug_probe(struct platform_device *pdev)
+static int rt5025_debug_probe(struct platform_device *pdev)
 {
        struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct rt5025_debug_info *di;
+       int ret = 0;
 
-       di = kzalloc(sizeof(*di), GFP_KERNEL);
+       di = devm_kzalloc(&pdev->dev, sizeof(*di), GFP_KERNEL);
        if (!di)
                return -ENOMEM;
 
        di->i2c = chip->i2c;
+       di->dev = &pdev->dev;
 
-       RTINFO("add debugfs for core RT5025");
-       client = chip->i2c;
+       RTINFO("add debugfs for RT5025");
        debugfs_rt_dent = debugfs_create_dir("rt5025_dbg", 0);
        if (!IS_ERR(debugfs_rt_dent)) {
-               debugfs_peek = debugfs_create_file("peek",
-               S_IFREG | S_IRUGO, debugfs_rt_dent,
-               (void *) "peek", &reg_debug_ops);
-
-               debugfs_poke = debugfs_create_file("poke",
+               rtdbg_data[0].info = di;
+               rtdbg_data[0].id = RT5025_DBG_REG;
+               debugfs_file[0] = debugfs_create_file("reg",
                S_IFREG | S_IRUGO, debugfs_rt_dent,
-               (void *) "poke", &reg_debug_ops);
+               (void *) &rtdbg_data[0], &reg_debug_ops);
 
-               debugfs_regs = debugfs_create_file("regs",
+               rtdbg_data[1].info = di;
+               rtdbg_data[1].id = RT5025_DBG_DATA;
+               debugfs_file[1] = debugfs_create_file("data",
                S_IFREG | S_IRUGO, debugfs_rt_dent,
-               (void *) "regs", &reg_debug_ops);
+               (void *) &rtdbg_data[1], &reg_debug_ops);
 
-               debugfs_reset_b = debugfs_create_file("reset_b",
+               rtdbg_data[2].info = di;
+               rtdbg_data[2].id = RT5025_DBG_REGS;
+               debugfs_file[2] = debugfs_create_file("regs",
                S_IFREG | S_IRUGO, debugfs_rt_dent,
-               (void *) "reset_b", &reg_debug_ops);
+               (void *) &rtdbg_data[2], &reg_debug_ops);
+       } else {
+               dev_err(&pdev->dev, "create debugfs failed\n");
+               ret = -EINVAL;
+               goto err_init;
        }
-
        platform_set_drvdata(pdev, di);
-
        return 0;
+err_init:
+       return ret;
 }
 
-static int __devexit rt5025_debug_remove(struct platform_device *pdev)
+static int rt5025_debug_remove(struct platform_device *pdev)
 {
-       struct rt5025_debug_info *di = platform_get_drvdata(pdev);
-
        if (!IS_ERR(debugfs_rt_dent))
                debugfs_remove_recursive(debugfs_rt_dent);
-
-       kfree(di);
        return 0;
 }
 
-static struct platform_driver rt5025_debug_driver = 
-{
+static const struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-debug",},
+       {},
+};
+
+static struct platform_driver rt5025_debug_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-debug",
+               .name = RT5025_DEV_NAME "-debug",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_debug_probe,
-       .remove = __devexit_p(rt5025_debug_remove),
+       .remove = rt5025_debug_remove,
 };
 
-static int __init rt5025_debug_init(void)
+static int rt5025_debug_init(void)
 {
        return platform_driver_register(&rt5025_debug_driver);
 }
 module_init(rt5025_debug_init);
 
-static void __exit rt5025_debug_exit(void)
+static void rt5025_debug_exit(void)
 {
        platform_driver_unregister(&rt5025_debug_driver);
 }
 module_exit(rt5025_debug_exit);
-
-MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Debug driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-debug");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-debug");
 MODULE_VERSION(RT5025_DRV_VER);
old mode 100644 (file)
new mode 100755 (executable)
index df23585..5690e05
@@ -2,51 +2,33 @@
  * I2C Driver for Richtek RT5025
  * Multi function device - multi functional baseband PMIC
  *
- * Copyright (C) 2013
+ * Copyright (C) 2014 Richtek Technology Corp.
  * 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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
-#include <linux/slab.h>
 #include <linux/mfd/rt5025.h>
 
-#define ROCKCHIP_I2C_RATE (200*1000)
-
 static inline int rt5025_read_device(struct i2c_client *i2c,
                                      int reg, int bytes, void *dest)
 {
-       #if 1
-       int ret;
-       unsigned char reg_addr = reg;
-       struct i2c_msg i2c_msg[2];
-       i2c_msg[0].addr = i2c->addr;
-       i2c_msg[0].flags = i2c->flags;
-       i2c_msg[0].len = 1;
-       i2c_msg[0].buf = &reg_addr;
-       i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
-       i2c_msg[1].addr = i2c->addr;
-       i2c_msg[1].flags = i2c->flags | I2C_M_RD;
-       i2c_msg[1].len = bytes;
-       i2c_msg[1].buf = dest;
-       i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
-       ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
-       #else
        int ret;
-       if (bytes > 1)
+
+       if (bytes > 1) {
                ret = i2c_smbus_read_i2c_block_data(i2c, reg, bytes, dest);
-       else {
+       else {
                ret = i2c_smbus_read_byte_data(i2c, reg);
                if (ret < 0)
                        return ret;
                *(unsigned char *)dest = (unsigned char)ret;
        }
-       #endif
        return ret;
 }
 
@@ -60,30 +42,15 @@ EXPORT_SYMBOL(rt5025_reg_block_read);
 static inline int rt5025_write_device(struct i2c_client *i2c,
                                      int reg, int bytes, void *dest)
 {
-       #if 1
-       int ret;
-       struct i2c_msg i2c_msg;
-       char *tx_buf = (char*)kmalloc(bytes+1, GFP_KERNEL);
-       tx_buf[0] = reg;
-       memcpy(tx_buf+1, dest, bytes);
-       i2c_msg.addr = i2c->addr;
-       i2c_msg.flags = i2c->flags;
-       i2c_msg.len = bytes + 1;
-       i2c_msg.buf = tx_buf;
-       i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
-       ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
-       kfree(tx_buf);
-       #else
        int ret;
-       if (bytes > 1)
+
+       if (bytes > 1) {
                ret = i2c_smbus_write_i2c_block_data(i2c, reg, bytes, dest);
-       else {
-               ret = i2c_smbus_write_byte_data(i2c, reg, dest);
+       else {
+               ret = i2c_smbus_write_byte_data(i2c, reg, *(u8 *)dest);
                if (ret < 0)
                        return ret;
-               *(unsigned char *)dest = (unsigned char)ret;
        }
-       #endif
        return ret;
 }
 
@@ -96,65 +63,28 @@ EXPORT_SYMBOL(rt5025_reg_block_write);
 
 int rt5025_reg_read(struct i2c_client *i2c, int reg)
 {
-       struct rt5025_chipchip = i2c_get_clientdata(i2c);
+       struct rt5025_chip *chip = i2c_get_clientdata(i2c);
        int ret;
-       #if 1
-       unsigned char reg_addr = reg;
-       unsigned char reg_data = 0;
-       struct i2c_msg i2c_msg[2];
-       RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
-           (unsigned int)i2c,(unsigned int)reg);
-       mutex_lock(&chip->io_lock);
-       i2c_msg[0].addr = i2c->addr;
-       i2c_msg[0].flags = i2c->flags;
-       i2c_msg[0].len = 1;
-       i2c_msg[0].buf = &reg_addr;
-       i2c_msg[0].scl_rate = ROCKCHIP_I2C_RATE;
-       i2c_msg[1].addr = i2c->addr;
-       i2c_msg[1].flags = i2c->flags | I2C_M_RD;
-       i2c_msg[1].len = 1;
-       i2c_msg[1].buf = &reg_data;
-       i2c_msg[1].scl_rate = ROCKCHIP_I2C_RATE;
-       ret = i2c_transfer(i2c->adapter, i2c_msg, 2);
-       mutex_unlock(&chip->io_lock);
-       #else
+
        RTINFO("I2C Read (client : 0x%x) reg = 0x%x\n",
-           (unsigned int)i2c,(unsigned int)reg);
+               (unsigned int) i2c, (unsigned int) reg);
        mutex_lock(&chip->io_lock);
        ret = i2c_smbus_read_byte_data(i2c, reg);
        mutex_unlock(&chip->io_lock);
-       #endif
-       return reg_data;
+       return ret;
 }
 EXPORT_SYMBOL(rt5025_reg_read);
 
 int rt5025_reg_write(struct i2c_client *i2c, int reg, unsigned char data)
 {
-       struct rt5025_chipchip = i2c_get_clientdata(i2c);
+       struct rt5025_chip *chip = i2c_get_clientdata(i2c);
        int ret;
-       #if 1
-       unsigned char xfer_data[2];
-       struct i2c_msg i2c_msg;
-       RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
-           (unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
-       xfer_data[0] = reg;
-       xfer_data[1] = data;
-       mutex_lock(&chip->io_lock);
-       i2c_msg.addr = i2c->addr;
-       i2c_msg.flags = i2c->flags;
-       i2c_msg.len = 2;
-       i2c_msg.buf = xfer_data;
-       i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
-       ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
-       mutex_unlock(&chip->io_lock);
-       #else
+
        RTINFO("I2C Write (client : 0x%x) reg = 0x%x, data = 0x%x\n",
-           (unsigned int)i2c,(unsigned int)reg,(unsigned int)data);
+               (unsigned int) i2c, (unsigned int) reg, (unsigned int) data);
        mutex_lock(&chip->io_lock);
        ret = i2c_smbus_write_byte_data(i2c, reg, data);
        mutex_unlock(&chip->io_lock);
-       #endif
-
        return ret;
 }
 EXPORT_SYMBOL(rt5025_reg_write);
@@ -165,25 +95,7 @@ int rt5025_assign_bits(struct i2c_client *i2c, int reg,
        struct rt5025_chip *chip = i2c_get_clientdata(i2c);
        unsigned char value;
        int ret;
-       #if 1
-       struct i2c_msg i2c_msg;
-       u8 xfer_data[2] = {0};
-       mutex_lock(&chip->io_lock);
-       ret = rt5025_read_device(i2c, reg, 1, &value);
-       if (ret < 0)
-               goto out;
-       
-       value &= ~mask;
-       value |= (data&mask);
-       xfer_data[0] = reg;
-       xfer_data[1] = value;
-       i2c_msg.addr = i2c->addr;
-       i2c_msg.flags = i2c->flags;
-       i2c_msg.len = 2;
-       i2c_msg.buf = xfer_data;
-       i2c_msg.scl_rate = ROCKCHIP_I2C_RATE;
-       ret = i2c_transfer(i2c->adapter, &i2c_msg, 1);
-       #else
+
        mutex_lock(&chip->io_lock);
 
        ret = rt5025_read_device(i2c, reg, 1, &value);
@@ -192,8 +104,7 @@ int rt5025_assign_bits(struct i2c_client *i2c, int reg,
                goto out;
        value &= ~mask;
        value |= (data&mask);
-       ret = i2c_smbus_write_byte_data(i2c,reg,value);
-       #endif
+       ret = i2c_smbus_write_byte_data(i2c, reg, value);
 out:
        mutex_unlock(&chip->io_lock);
        return ret;
@@ -203,90 +114,101 @@ EXPORT_SYMBOL(rt5025_assign_bits);
 int rt5025_set_bits(struct i2c_client *i2c, int reg,
                unsigned char mask)
 {
-       return rt5025_assign_bits(i2c,reg,mask,mask);
+       return rt5025_assign_bits(i2c, reg, mask, mask);
 }
 EXPORT_SYMBOL(rt5025_set_bits);
 
 int rt5025_clr_bits(struct i2c_client *i2c, int reg,
                unsigned char mask)
 {
-       return rt5025_assign_bits(i2c,reg,mask,0);
+       return rt5025_assign_bits(i2c, reg, mask, 0);
 }
 EXPORT_SYMBOL(rt5025_clr_bits);
 
-static int __devinit rt5025_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int rt_parse_dt(struct rt5025_chip *chip, struct device *dev)
+{
+       return 0;
+}
+
+static int rt_parse_pdata(struct rt5025_chip *chip, struct device *dev)
+{
+       return 0;
+}
+
+static int rt5025_i2c_probe(struct i2c_client *client,
+       const struct i2c_device_id *id)
 {
        struct rt5025_platform_data *pdata = client->dev.platform_data;
        struct rt5025_chip *chip;
+       bool use_dt = client->dev.of_node;
        int ret = 0;
-       u8 val;
-
-       if (!pdata)
-               return -EINVAL;
+       u8 val = 0;
 
-       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+       chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
        if (!chip)
                return -ENOMEM;
 
-       chip->irq = client->irq;
-       chip->i2c = client;
-       chip->dev = &client->dev;
-
-#if 0
-       if (pdata->event_callback)
-       {
-               chip->event_callback = kzalloc(sizeof(struct rt5025_event_callback), GFP_KERNEL);
-               memcpy(chip->event_callback, pdata->event_callback, sizeof(struct rt5025_event_callback));
+       if (use_dt) {
+               rt_parse_dt(chip, &client->dev);
+       } else {
+               if (!pdata) {
+                       ret = -EINVAL;
+                       goto err_init;
+               }
+               rt_parse_pdata(chip, &client->dev);
        }
-#endif /* #if 0 */
 
-       i2c_set_clientdata(client, chip);
+       chip->i2c = client;
+       chip->dev = &client->dev;
        mutex_init(&chip->io_lock);
-       
-       rt5025_read_device(client,0x00,1,&val);
-       if (val != 0x81){
-               printk("The PMIC is not RT5025\n");
+       i2c_set_clientdata(client, chip);
+       /* off event */
+       rt5025_read_device(client, 0x20, 1, &val);
+       RTINFO("off event = %d\n", val);
+
+       rt5025_read_device(client, 0x00, 1, &val);
+       if (val != 0x81) {
+               dev_info(&client->dev, "The PMIC is not RT5025\n");
                return -ENODEV;
        }
+
        ret = rt5025_core_init(chip, pdata);
-       if (ret < 0)
-               dev_err(chip->dev, "rt5025_core_init_fail\n");
-       else
-               pr_info("RT5025 Initialize successfully\n");
+       if (ret < 0) {
+               dev_err(&client->dev, "rt5025_core_init_fail\n");
+               goto err_init;
+       }
 
+       dev_info(&client->dev, "driver successfully probed\n");
        if (pdata && pdata->pre_init) {
                ret = pdata->pre_init(chip);
-               if (ret != 0) {
+               if (ret != 0)
                        dev_err(chip->dev, "pre_init() failed: %d\n", ret);
-               }
        }
-       
+
        if (pdata && pdata->post_init) {
                ret = pdata->post_init();
-               if (ret != 0) {
+               if (ret != 0)
                        dev_err(chip->dev, "post_init() failed: %d\n", ret);
-               }
        }
-
+       return 0;
+err_init:
        return ret;
 
 }
 
-static int __devexit rt5025_i2c_remove(struct i2c_client *client)
+static int rt5025_i2c_remove(struct i2c_client *client)
 {
        struct rt5025_chip *chip = i2c_get_clientdata(client);
+
        rt5025_core_deinit(chip);
-       #if 0
-       if (chip->event_callback)
-               kfree(chip->event_callback);
-       #endif
-       kfree(chip);
+       dev_info(&client->dev, "%s\n", __func__);
        return 0;
 }
 
 static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 {
        struct rt5025_chip *chip = i2c_get_clientdata(client);
+
        chip->suspend = 1;
        RTINFO("\n");
        return 0;
@@ -295,47 +217,49 @@ static int rt5025_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
 static int rt5025_i2c_resume(struct i2c_client *client)
 {
        struct rt5025_chip *chip = i2c_get_clientdata(client);
+
        chip->suspend = 0;
        RTINFO("\n");
        return 0;
 }
 
 static const struct i2c_device_id rt5025_id_table[] = {
-       { RT5025_DEVICE_NAME, 0 },
+       { RT5025_DEV_NAME, 0 },
        { },
 };
 MODULE_DEVICE_TABLE(i2c, rt5025_id_table);
 
-static struct i2c_driver rt5025_driver = {
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025",},
+       {},
+};
+
+static struct i2c_driver rt5025_i2c_driver = {
        .driver = {
-               .name   = RT5025_DEVICE_NAME,
+               .name   = RT5025_DEV_NAME,
                .owner  = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe          = rt5025_i2c_probe,
-       .remove         = __devexit_p(rt5025_i2c_remove),
+       .remove         = rt5025_i2c_remove,
        .suspend        = rt5025_i2c_suspend,
        .resume         = rt5025_i2c_resume,
        .id_table       = rt5025_id_table,
 };
 
-static int __init rt5025_i2c_init(void)
+static int rt5025_i2c_init(void)
 {
-       int ret;
-
-       ret = i2c_add_driver(&rt5025_driver);
-       if (ret != 0)
-               pr_err("Failed to register RT5025 I2C driver: %d\n", ret);
-       return ret;
+       return i2c_add_driver(&rt5025_i2c_driver);
 }
 subsys_initcall_sync(rt5025_i2c_init);
 
-static void __exit rt5025_i2c_exit(void)
+static void rt5025_i2c_exit(void)
 {
-       i2c_del_driver(&rt5025_driver);
+       i2c_del_driver(&rt5025_i2c_driver);
 }
 module_exit(rt5025_i2c_exit);
 
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("I2C Driver for Richtek RT5025");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
 MODULE_VERSION(RT5025_DRV_VER);
old mode 100644 (file)
new mode 100755 (executable)
index 7a324c2..67d8a82
 /*
  *  drivers/mfd/rt5025-irq.c
- *  Driver foo Richtek RT5025 PMIC irq
+ *  Driver for Richtek RT5025 PMIC IRQ driver
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2014 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/err.h>
-#include <linux/i2c.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/wakelock.h>
-#include <linux/delay.h>
-
-#include <linux/gpio.h>
-#include <linux/irq.h>
-#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
 
 #include <linux/mfd/rt5025.h>
 #include <linux/mfd/rt5025-irq.h>
 
 struct rt5025_irq_info {
        struct i2c_client *i2c;
-       struct device *dev;
        struct rt5025_chip *chip;
-       struct workqueue_struct *wq;
-       struct rt5025_event_callback *event_cb;
-       struct delayed_work delayed_work;
-       struct wake_lock irq_wake_lock;
-       int intr_pin;
+       struct device *dev;
        int irq;
-       int suspend;
-       int acin_cnt;
-       int usbin_cnt;
+       unsigned char suspend:1;
+       struct delayed_work irq_delayed_work;
 };
 
-static void rt5025_work_func(struct work_struct *work)
+static irqreturn_t rt5025_irq_handler(int irqno, void *param)
 {
-       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[6] = {0};
-       unsigned char irq_enable[6] = {0};
-       uint32_t chg_event = 0, pwr_event = 0;
+       struct rt5025_irq_info *ii = param;
+       unsigned char regval[6];
+       unsigned int irq_event = 0;
+       int ret = 0;
 
-       //Add this to prevent i2c xfer before i2c chip is in suspend mode
-       if (ii->suspend)
-       {
-               queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(1));
-               return;
+       if (ii->suspend) {
+               schedule_delayed_work(&ii->irq_delayed_work,
+                       msecs_to_jiffies(10));
+               goto irq_fin;
        }
 
-       #ifdef CONFIG_POWER_RT5025
-       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;
+       ret = rt5025_reg_read(ii->i2c, RT5025_REG_IRQFLG);
+       if (ret < 0) {
+               dev_err(ii->dev, "read gauge irq event fail\n");
+       } else {
+               irq_event = ret;
+               RTINFO("gauge event %02x\n", irq_event);
+               #ifdef CONFIG_BATTERY_RT5025
+               if (irq_event)
+                       rt5025_gauge_irq_handler(ii->chip->battery_info,
+                               irq_event&(~RT5025_TALRT_MASK));
+               #endif /* #ifdef CONFIG_RTC_RT5025 */
        }
-       #endif
 
-       #if 0
-       if (rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 10, irq_stat) >= 0)
-       {
-       #endif
-               /* backup the irq enable bit */
-               irq_enable[0] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN1);
-               irq_enable[1] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN2);
-               irq_enable[2] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN3);
-               irq_enable[3] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN4);
-               irq_enable[4] = rt5025_reg_read(ii->i2c, RT5025_REG_IRQEN5);
-               irq_enable[5] = rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQEN);
-               #if 1
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]&(~RT5025_CHTERMI_MASK));
+       ret = rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN1, 6, regval);
+       if (ret < 0) {
+               dev_err(ii->dev, "read charger irq event fail\n");
+       } else {
+               #ifdef CONFIG_BATTERY_RT5025
+               /*combine gauge talrt irq into charger event*/
+               irq_event = irq_event&RT5025_TALRT_MASK;
+               irq_event <<= 24;
+               irq_event |= (regval[1] << 16 | regval[3] << 8 | regval[5]);
                #else
-               /* disable all irq enable bit first */
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]&RT5025_ADAPIRQ_MASK);
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, 0x00);
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, 0x00);
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, 0x00);
-               rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, 0x00);
-               rt5025_reg_write(ii->i2c, RT5025_REG_GAUGEIRQEN, 0x00);
-               #endif //#if 0
-               /* read irq status bit */
-               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[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++;
-                               if (ii->chip->power_info->chg_term > 3)
-                                       ii->chip->power_info->chg_term = 4;
-                       }
-
-                       if (chg_event & CHG_EVENT_CHRCHGI)
-                               ii->chip->power_info->chg_term = 0;
-
-                       if (chg_event & (CHG_EVENT_CHSLPI_INAC | CHG_EVENT_CHSLPI_INUSB))
-                       {
-                               ii->chip->power_info->chg_term = 0;
-                               if (chg_event & CHG_EVENT_CHSLPI_INAC)
-                                       ii->acin_cnt = 0;
-                               if (chg_event & CHG_EVENT_CHSLPI_INUSB)
-                                       ii->usbin_cnt = 0;
-                               
-                       }
-
-                       if (chg_event & (CHG_EVENT_INAC_PLUGIN | CHG_EVENT_INUSB_PLUGIN))
-                       {
-                               RTINFO("acin_cnt %d, usbin_cnt %d\n", ii->acin_cnt, ii->usbin_cnt);
-                               if (ii->acin_cnt == 0 && ii->usbin_cnt == 0)
-                               {
-                                       #if 1
-                                       rt5025_charger_reset_and_reinit(ii->chip->power_info);
-                                       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]);
-                                       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]&(~RT5025_CHTERMI_MASK));
-                                       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_enable[2]);
-                                       #else
-                                       rt5025_set_charging_buck(ii->i2c, 0);
-                                       mdelay(50);
-                                       rt5025_set_charging_buck(ii->i2c, 1);
-                                       mdelay(100);
-                                       rt5025_set_charging_buck(ii->i2c, 0);
-                                       mdelay(50);
-                                       rt5025_set_charging_buck(ii->i2c, 1);
-                                       mdelay(400);
-                                       #endif /* #if 1 */
-                               }
-
-                               if (chg_event & CHG_EVENT_INAC_PLUGIN)
-                                       ii->acin_cnt = 1;
-                               if (chg_event & CHG_EVENT_INUSB_PLUGIN)
-                                       ii->usbin_cnt = 1;
-                               RTINFO("acin_cnt %d, usbin_cnt %d\n", ii->acin_cnt, ii->usbin_cnt);
-                       }
-
-                       if (ii->chip->power_info->chg_term <= 3)
-                               rt5025_power_charge_detect(ii->chip->power_info);
-
-               }
-               #endif /* CONFIG_POWER_RT5025 */
-               if (ii->event_cb)
-               {
-                       if (chg_event)
-                               ii->event_cb->charger_event_callback(chg_event);
-                       if (pwr_event)
-                               ii->event_cb->power_event_callkback(pwr_event);
-               }
-       #if 0
+               irq_event = regval[1] << 16 | regval[3] << 8 | regval[5];
+               #endif
+               RTINFO("chg event %08x\n", irq_event);
+               #ifdef CONFIG_CHARGER_RT5025
+               if (irq_event)
+                       rt5025_charger_irq_handler(ii->chip->charger_info,
+                               irq_event);
+               #endif /* #ifdef CONFIG_CHARGER_RT5025 */
        }
-       else
-               dev_err(ii->dev, "read irq stat io fail\n");
-       #endif
-       
-
-       #ifdef CONFIG_POWER_RT5025
-       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 */
 
-       #if 1
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]);
-       #else
-       /* restore all irq enable bit */
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_enable[0]);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_enable[1]);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_enable[2]);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, irq_enable[3]);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, irq_enable[4]);
-       if (rt5025_reg_read(ii->i2c, RT5025_REG_GAUGEIRQEN) == 0)
-               rt5025_reg_write(ii->i2c, RT5025_REG_GAUGEIRQEN, irq_enable[5]);
-       #endif //#if 0
-
-       //enable_irq(ii->irq);
+       ret = rt5025_reg_block_read(ii->i2c, RT5025_REG_IRQEN4, 4, regval);
+       if (ret < 0) {
+               dev_err(ii->dev, "read misc irq event fail\n");
+       } else {
+               irq_event = regval[1] << 8 | regval[3];
+               RTINFO("misc event %04x\n", irq_event);
+               #ifdef CONFIG_MISC_RT5025
+               if (irq_event)
+                       rt5025_misc_irq_handler(ii->chip->misc_info, irq_event);
+               #endif /* #ifdef CONFIG_MISC_RT5025 */
+       }
+irq_fin:
+       return IRQ_HANDLED;
 }
 
-static irqreturn_t rt5025_interrupt(int irqno, void *param)
+static void rt5025_irq_delayed_work(struct work_struct *work)
 {
-       struct rt5025_irq_info *ii = (struct rt5025_irq_info *)param;
+       struct rt5025_irq_info *ii = (struct rt5025_irq_info *)container_of(work,
+               struct rt5025_irq_info, irq_delayed_work.work);
 
-       //disable_irq_nosync(ii->irq);
-       wake_lock_timeout(&ii->irq_wake_lock, 1*HZ);
-       queue_delayed_work(ii->wq, &ii->delayed_work, 0);
-       return IRQ_HANDLED;
+       rt5025_irq_handler(ii->irq, ii);
 }
 
-static int __devinit rt5025_interrupt_init(struct rt5025_irq_info* ii)
+static int rt_parse_dt(struct rt5025_irq_info *ii, struct device *dev)
 {
-       int ret = 0;
-
-       RTINFO("\n");
-       ii->wq = create_workqueue("rt5025_wq");
-       INIT_DELAYED_WORK(&ii->delayed_work, rt5025_work_func);
-
-       #if 0
-       if (gpio_is_valid(ii->intr_pin))
-       {
-               ret = gpio_request(ii->intr_pin, "rt5025_interrupt");
-               if (ret)
-                       return ret;
-
-               ret = gpio_direction_input(ii->intr_pin);
-               if (ret)
-                       return ret;
-       #endif
-
-               if (request_irq(ii->irq, rt5025_interrupt, IRQ_TYPE_EDGE_FALLING|IRQF_DISABLED, "RT5025_IRQ", ii))
-               {
-                       dev_err(ii->dev, "couldn't allocate IRQ_NO(%d) !\n", ii->irq);
-                       return -EINVAL;
-               }
-               enable_irq_wake(ii->irq);
-               queue_delayed_work(ii->wq, &ii->delayed_work, msecs_to_jiffies(100));
-       #if 0
-
-               if (!gpio_get_value(ii->intr_pin))
-               {
-                       //disable_irq_nosync(ii->irq);
-                       queue_delayed_work(ii->wq, &ii->delayed_work, 0);
+       #ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+       int val;
+
+       val = of_get_named_gpio(np, "rt,irq-gpio", 0);
+       if (gpio_is_valid(val)) {
+               if (gpio_request(val, "rt5025-irq") >= 0) {
+                       gpio_direction_input(val);
+                       ii->irq = gpio_to_irq(val);
+               } else {
+                       ii->irq = -1;
                }
+       } else {
+               ii->irq = -1;
        }
-       else
-               return -EINVAL;
-       #endif
-
-       return ret;
+       #endif /* #ifdef CONFIG_OF */
+       RTINFO("\n");
+       return 0;
 }
 
-static void __devexit rt5025_interrupt_deinit(struct rt5025_irq_info* ii)
+static int rt_parse_pdata(struct rt5025_irq_info *ii, struct device *dev)
 {
-       if (ii->irq)
-               free_irq(ii->irq, ii);
-
-       if (ii->wq)
-       {
-               cancel_delayed_work_sync(&ii->delayed_work);
-               flush_workqueue(ii->wq);
-               destroy_workqueue(ii->wq);
+       struct rt5025_irq_data *pdata = dev->platform_data;
+
+       if (gpio_is_valid(pdata->irq_gpio)) {
+               if (gpio_request(pdata->irq_gpio, "rt5025-irq") >= 0) {
+                       gpio_direction_input(pdata->irq_gpio);
+                       ii->irq = gpio_to_irq(pdata->irq_gpio);
+               } else {
+                       ii->irq = -1;
+               }
+       } else {
+               ii->irq = -1;
        }
-}
-
-static int __devinit rt5025_irq_reg_init(struct rt5025_irq_info* ii, struct rt5025_irq_data* irq_data)
-{
        RTINFO("\n");
-       // will just enable the interrupt that we want
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN1, irq_data->irq_enable1.val);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN2, irq_data->irq_enable2.val);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN3, irq_data->irq_enable3.val);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN4, irq_data->irq_enable4.val);
-       rt5025_reg_write(ii->i2c, RT5025_REG_IRQEN5, irq_data->irq_enable5.val);
        return 0;
 }
 
-static int __devinit rt5025_irq_probe(struct platform_device *pdev)
+static int 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_platform_data *pdata = (pdev->dev.parent)->platform_data;
        struct rt5025_irq_info *ii;
+       bool use_dt = pdev->dev.of_node;
+       int ret;
 
-       RTINFO("\n");
-       ii = kzalloc(sizeof(*ii), GFP_KERNEL);
+       ii = devm_kzalloc(&pdev->dev, sizeof(*ii), GFP_KERNEL);
        if (!ii)
                return -ENOMEM;
 
        ii->i2c = chip->i2c;
-       ii->dev = &pdev->dev;
        ii->chip = chip;
-       ii->intr_pin = pdata->intr_pin;
-       ii->irq = chip->irq;//gpio_to_irq(pdata->intr_pin);
-       if (pdata->cb)
-               ii->event_cb = pdata->cb;
-       wake_lock_init(&ii->irq_wake_lock, WAKE_LOCK_SUSPEND, "rt_irq_wake");
+       ii->dev = &pdev->dev;
+       if (use_dt) {
+               rt_parse_dt(ii, &pdev->dev);
+       } else {
+               if (!pdata)
+                       goto out_dev;
+               pdev->dev.platform_data = pdata->irq_pdata;
+               rt_parse_pdata(ii, &pdev->dev);
+               dev_info(&pdev->dev, "ii->irq %d\n", ii->irq);
+       }
 
-       rt5025_irq_reg_init(ii, pdata->irq_data);
-       rt5025_interrupt_init(ii);
+       INIT_DELAYED_WORK(&ii->irq_delayed_work, rt5025_irq_delayed_work);
 
        platform_set_drvdata(pdev, ii);
-       RTINFO("\n");
+       if (ii->irq >= 0) {
+               ret = devm_request_irq(&pdev->dev, ii->irq, rt5025_irq_handler,
+                       IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND, "rt5025-irq", ii);
+               if (ret != 0) {
+                       dev_err(&pdev->dev, "request threaded irq fail\n");
+                       goto out_dev;
+               }
+               enable_irq_wake(ii->irq);
+               schedule_delayed_work(&ii->irq_delayed_work, 1*HZ);
+       }
+       dev_info(&pdev->dev, "driver successfully loaded\n");
        return 0;
+out_dev:
+       return -EINVAL;
 }
 
-static int __devexit rt5025_irq_remove(struct platform_device *pdev)
+static int rt5025_irq_remove(struct platform_device *pdev)
 {
        struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
 
-       wake_lock_destroy(&ii->irq_wake_lock);
-       rt5025_interrupt_deinit(ii);
-       platform_set_drvdata(pdev, NULL);
-       kfree(ii);
-       RTINFO("\n");
+       if (ii->irq >= 0)
+               devm_free_irq(&pdev->dev, ii->irq, ii);
        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);
-       }
-       RTINFO("\n");
-}
-
 static int rt5025_irq_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
 
-       RTINFO("\n");
        ii->suspend = 1;
        return 0;
 }
@@ -339,38 +207,42 @@ static int rt5025_irq_resume(struct platform_device *pdev)
 {
        struct rt5025_irq_info *ii = platform_get_drvdata(pdev);
 
-       RTINFO("\n");
        ii->suspend = 0;
        return 0;
 }
 
-static struct platform_driver rt5025_irq_driver = 
-{
+static const struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-irq",},
+       {},
+};
+
+static struct platform_driver rt5025_irq_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-irq",
+               .name = RT5025_DEV_NAME "-irq",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_irq_probe,
-       .remove = __devexit_p(rt5025_irq_remove),
-       .shutdown = rt5025_irq_shutdown,
+       .remove = rt5025_irq_remove,
        .suspend = rt5025_irq_suspend,
        .resume = rt5025_irq_resume,
 };
 
-static int __init rt5025_irq_init(void)
+static int rt5025_irq_init(void)
 {
        return platform_driver_register(&rt5025_irq_driver);
 }
-module_init(rt5025_irq_init);
+device_initcall(rt5025_irq_init);
 
-static void __exit rt5025_irq_exit(void)
+static void rt5025_irq_exit(void)
 {
        platform_driver_unregister(&rt5025_irq_driver);
 }
+
 module_exit(rt5025_irq_exit);
 
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("IRQ driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-irq");
+MODULE_ALIAS("platform:"RT5025_DEV_NAME "-irq");
 MODULE_VERSION(RT5025_DRV_VER);
old mode 100644 (file)
new mode 100755 (executable)
index e84475a..55dee75
@@ -2,12 +2,13 @@
  *  drivers/mfd/rt5025-misc.c
  *  Driver foo Richtek RT5025 PMIC Misc Part
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2014 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/platform_device.h>
-#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/power_supply.h>
 
 #include <linux/mfd/rt5025.h>
 #include <linux/mfd/rt5025-misc.h>
 
-struct rt5025_misc_info {
-       struct i2c_client *i2c;
+static unsigned char misc_init_regval[] = {
+       0x2A,   /* reg 0x15 */
+       0x00,   /* reg 0x16 */
+       0x60,   /* reg 0x17 */
+       0x16,   /* reg 0x19 */
+       0x60,   /* reg 0x1A */
+       0x0C,   /* reg 0x1B */
+       0xF3,   /* reg 0x36 */
+       0x90,   /* reg 0x38 */
 };
 
 static struct i2c_client *g_shdn;
-void rt5025_power_off(void)
+static bool rt_pm_off;
+static void rt5025_power_off(void)
 {
-       rt5025_reg_write(g_shdn, RT5025_CHENH_REG, 0x00);
-       rt5025_reg_write(g_shdn, RT5025_CHENL_REG, 0x80);
-       rt5025_set_bits(g_shdn, RT5025_SHDNCTRL_REG, RT5025_SHDNCTRL_MASK);
+       rt5025_reg_write(g_shdn, RT5025_REG_CHANNELH, 0x00);
+       rt5025_reg_write(g_shdn, RT5025_REG_CHANNELL, 0x80);
+       rt5025_set_bits(g_shdn, RT5025_REG_MISC3, RT5025_SHDNCTRL_MASK);
 }
 EXPORT_SYMBOL(rt5025_power_off);
 
 int rt5025_cable_exist(void)
 {
        int ret = 0;
-       ret = rt5025_reg_read(g_shdn, 0x01);
-       if (ret < 0)
-               return 0;
-       else
-       {
-               if (ret&0x3)
-                       return 1;
-               return 0;
+       #ifdef CONFIG_CHARGER_RT5025
+       struct power_supply *psy = power_supply_get_by_name("rt-charger");
+       union power_supply_propval pval;
+
+       if (!psy) {
+               pr_err(" couldn't get charger power supply\n");
+       } else {
+               ret = psy->get_property(psy,
+                       POWER_SUPPLY_PROP_CHARGE_NOW, &pval);
+               if (ret < 0) {
+                       ret = 0;
+               } else {
+                       if (pval.intval > POWER_SUPPLY_TYPE_BATTERY)
+                               ret = 1;
+                       else
+                               ret = 0;
+               }
+       }
+       #else
+       ret = rt5025_reg_read(g_shdn, RT5025_REG_CHGCTL1);
+       if (ret < 0) {
+               pr_err("couldn't get cable status\n");
+               ret = 0;
+       } else {
+               if (ret & RT5025_CABLEIN_MASK)
+                       ret = 1;
+               else
+                       ret = 0;
        }
+       #endif /* #ifdef CONFIG_CHARGER_RT5025 */
+       return ret;
 }
 EXPORT_SYMBOL(rt5025_cable_exist);
 
-static int __devinit rt5025_misc_reg_init(struct i2c_client *client, struct rt5025_misc_data *md)
+static void rt5025_general_irq_handler(void *info, int eventno)
 {
-       int ret = 0;
-       
-       rt5025_reg_write(client, RT5025_RESETCTRL_REG, md->RSTCtrl.val);
-       rt5025_assign_bits(client, RT5025_VSYSULVO_REG, RT5025_VSYSOFF_MASK, md->VSYSCtrl.val);
-       rt5025_reg_write(client, RT5025_PWRONCTRL_REG, md->PwrOnCfg.val);
-       rt5025_reg_write(client, RT5025_SHDNCTRL_REG, md->SHDNCtrl.val);
-       rt5025_reg_write(client, RT5025_PWROFFEN_REG, md->PwrOffCond.val);
+       struct rt5025_misc_info *mi = info;
 
-       return ret;
+       RTINFO("eventno=%02d\n", eventno);
+
+       switch (eventno) {
+       case MISCEVENT_RESETB:
+               dev_warn(mi->dev, "RESETB event trigger\n");
+               break;
+       case MISCEVENT_KPSHDN:
+               dev_warn(mi->dev, "PwrKey force shdn\n");
+               break;
+       case MISCEVENT_SYSLV:
+               dev_warn(mi->dev, "syslv event trigger\n");
+               break;
+       case MISCEVENT_DCDC4LVHV:
+               dev_warn(mi->dev, "DCDC4LVHV event trigger\n");
+               break;
+       case MISCEVENT_DCDC3LV:
+               dev_warn(mi->dev, "DCDC3LV event trigger\n");
+               break;
+       case MISCEVENT_DCDC2LV:
+               dev_warn(mi->dev, "DCDC2LV event trigger\n");
+               break;
+       case MISCEVENT_DCDC1LV:
+               dev_warn(mi->dev, "DCDC2LV event trigger\n");
+               break;
+       case MISCEVENT_OT:
+               dev_warn(mi->dev, "Over temperature event trigger\n");
+               break;
+       default:
+               break;
+       }
+}
+
+static rt_irq_handler rt_miscirq_handler[MISCEVENT_MAX] = {
+       [MISCEVENT_GPIO0_IE] = rt5025_general_irq_handler,
+       [MISCEVENT_GPIO1_IE] = rt5025_general_irq_handler,
+       [MISCEVENT_GPIO2_IE] = rt5025_general_irq_handler,
+       [MISCEVENT_RESETB] = rt5025_general_irq_handler,
+       [MISCEVENT_PWRONF] = rt5025_general_irq_handler,
+       [MISCEVENT_PWRONR] = rt5025_general_irq_handler,
+       [MISCEVENT_KPSHDN] = rt5025_general_irq_handler,
+       [MISCEVENT_SYSLV] = rt5025_general_irq_handler,
+       [MISCEVENT_DCDC4LVHV] = rt5025_general_irq_handler,
+       [MISCEVENT_PWRONLP_IRQ] = rt5025_general_irq_handler,
+       [MISCEVENT_PWRONSP_IRQ] = rt5025_general_irq_handler,
+       [MISCEVENT_DCDC3LV] = rt5025_general_irq_handler,
+       [MISCEVENT_DCDC2LV] = rt5025_general_irq_handler,
+       [MISCEVENT_DCDC1LV] = rt5025_general_irq_handler,
+       [MISCEVENT_OT] = rt5025_general_irq_handler,
+};
+
+void rt5025_misc_irq_handler(struct rt5025_misc_info *ci, unsigned int irqevent)
+{
+       int i;
+       unsigned int enable_irq_event = (misc_init_regval[6] << 8) |
+               misc_init_regval[7];
+       unsigned int final_irq_event = irqevent&enable_irq_event;
+
+       for (i = 0; i < MISCEVENT_MAX; i++) {
+               if ((final_irq_event&(1 << i)) && rt_miscirq_handler[i])
+                       rt_miscirq_handler[i](ci, i);
+       }
+}
+EXPORT_SYMBOL(rt5025_misc_irq_handler);
+
+static int  rt5025_misc_reginit(struct i2c_client *client)
+{
+       rt5025_reg_write(client, RT5025_REG_MISC1, misc_init_regval[0]);
+       rt5025_reg_write(client, RT5025_REG_ONEVENT, misc_init_regval[1]);
+       rt5025_assign_bits(client, RT5025_REG_DCDCONOFF,
+               RT5025_VSYSOFF_MASK, misc_init_regval[2]);
+       rt5025_reg_write(client, RT5025_REG_MISC2, misc_init_regval[3]);
+       rt5025_reg_write(client, RT5025_REG_MISC3, misc_init_regval[4]);
+       rt5025_reg_write(client, RT5025_REG_MISC4, misc_init_regval[5]);
+       /*set all to be masked*/
+       rt5025_reg_write(client, RT5025_REG_IRQEN4, 0x00);
+       rt5025_reg_write(client, RT5025_REG_IRQEN5, 0x00);
+       /*clear the old irq status*/
+       rt5025_reg_read(client, RT5025_REG_IRQSTAT4);
+       rt5025_reg_read(client, RT5025_REG_IRQSTAT5);
+       /*set enable irqs as we want*/
+       rt5025_reg_write(client, RT5025_REG_IRQEN4, misc_init_regval[6]);
+       rt5025_reg_write(client, RT5025_REG_IRQEN5, misc_init_regval[7]);
+       return 0;
+}
+
+static int rt_parse_dt(struct rt5025_misc_info *mi, struct device *dev)
+{
+       int rc;
+       #ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+       unsigned int val;
+
+       rc = of_property_read_u32(np, "rt,vsyslv", &val);
+       if (rc < 0) {
+               dev_info(dev, "no system lv value, use default value\n");
+       } else {
+               if (val > RT5025_VOFF_MAX)
+                       val = RT5025_VOFF_MAX;
+               misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
+               misc_init_regval[2] |= val << RT5025_VSYSOFF_SHFT;
+       }
+
+       rc = of_property_read_u32(np, "rt,shdnlpress_time", &val);
+       if (rc < 0) {
+               dev_info(dev, "no shdnlpress time, use default value\n");
+       } else {
+               if (val > RT5025_SHDNPRESS_MAX)
+                       val = RT5025_SHDNPRESS_MAX;
+               misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
+               misc_init_regval[3] |= val << RT5025_SHDNLPRESS_SHFT;
+       }
+
+       rc = of_property_read_u32(np, "rt,startlpress_time", &val);
+       if (rc < 0) {
+               dev_err(dev, "no start_lpress, use default value\n");
+       } else {
+               if (val > RT5025_STARTIME_MAX)
+                       val = RT5025_STARTIME_MAX;
+               misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
+               misc_init_regval[3] |= val << RT5025_STARTLPRESS_SHFT;
+       }
+
+       if (of_property_read_bool(np, "rt,vsyslv_enshdn"))
+               misc_init_regval[5] |= RT5025_VSYSLVSHDN_MASK;
+       else
+               misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
+       #endif
+
+       rt_pm_off = of_property_read_bool(np, "rt,system-power-controller");
+       /* #ifdef CONFIG_OF */
+       rc = rt5025_misc_reginit(mi->i2c);
+       return rc;
+}
+
+static int rt_parse_pdata(struct rt5025_misc_info *mi, struct device *dev)
+{
+       struct rt5025_misc_data  *pdata = dev->platform_data;
+       int rc = 0;
+
+       /*system low voltage*/
+       misc_init_regval[2] &= ~RT5025_VSYSOFF_MASK;
+       misc_init_regval[2] |= (pdata->vsyslv << RT5025_VSYSOFF_SHFT);
+       /*shutdown long press time*/
+       misc_init_regval[3] &= ~RT5025_SHDNLPRESS_MASK;
+       misc_init_regval[3] |= (pdata->shdnlpress_time <<
+               RT5025_SHDNLPRESS_SHFT);
+       /*start long press time*/
+       misc_init_regval[3] &= ~RT5025_STARTLPRESS_MASK;
+       misc_init_regval[3] |= (pdata->startlpress_time <<
+               RT5025_STARTLPRESS_SHFT);
+       /*systemlv enable shutdown*/
+       misc_init_regval[5] &= ~RT5025_VSYSLVSHDN_MASK;
+       misc_init_regval[5] |= (pdata->vsyslv_enshdn <<
+               RT5025_VSYSLVSHDN_SHFT);
+       rc = rt5025_misc_reginit(mi->i2c);
+       return rc;
 }
 
-static int __devinit rt5025_misc_probe(struct platform_device *pdev)
+static int 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_platform_data *pdata = (pdev->dev.parent)->platform_data;
        struct rt5025_misc_info *mi;
+       bool use_dt = pdev->dev.of_node;
+       int ret = 0;
 
-       mi = kzalloc(sizeof(*mi), GFP_KERNEL);
+       mi = devm_kzalloc(&pdev->dev, sizeof(*mi), GFP_KERNEL);
        if (!mi)
                return -ENOMEM;
 
        mi->i2c = chip->i2c;
-       rt5025_misc_reg_init(mi->i2c, pdata->misc_data);
-
-       //for shutdown control
+       mi->dev = &pdev->dev;
+       if (use_dt) {
+               rt_parse_dt(mi, &pdev->dev);
+       } else {
+               if (!pdata) {
+                       dev_err(&pdev->dev, "no initial platform data\n");
+                       ret = -EINVAL;
+                       goto err_init;
+               }
+               pdev->dev.platform_data = pdata->misc_pdata;
+               rt_parse_pdata(mi, &pdev->dev);
+       }
+       /*for shutdown control*/
        g_shdn = chip->i2c;
 
+       if (rt_pm_off && !pm_power_off)
+               pm_power_off = rt5025_power_off;
+
        platform_set_drvdata(pdev, mi);
+       chip->misc_info = mi;
+       dev_info(&pdev->dev, "driver successfully loaded\n");
        return 0;
+err_init:
+       return ret;
 }
 
-static int __devexit rt5025_misc_remove(struct platform_device *pdev)
+static int rt5025_misc_remove(struct platform_device *pdev)
 {
-       struct rt5025_misc_info *mi = platform_get_drvdata(pdev);
-
-       kfree(mi);
-       platform_set_drvdata(pdev, NULL);
+       dev_info(&pdev->dev, "%s\n", __func__);
        return 0;
 }
 
-static struct platform_driver rt5025_misc_driver = 
-{
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-misc",},
+       {},
+};
+
+static struct platform_driver rt5025_misc_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-misc",
+               .name = RT5025_DEV_NAME "-misc",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_misc_probe,
-       .remove = __devexit_p(rt5025_misc_remove),
+       .remove = rt5025_misc_remove,
 };
 
-static int __init rt5025_misc_init(void)
+static int rt5025_misc_init(void)
 {
        return platform_driver_register(&rt5025_misc_driver);
 }
-module_init(rt5025_misc_init);
+subsys_initcall(rt5025_misc_init);
 
-static void __exit rt5025_misc_exit(void)
+static void rt5025_misc_exit(void)
 {
        platform_driver_unregister(&rt5025_misc_driver);
 }
 module_exit(rt5025_misc_exit);
 
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
 MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
 MODULE_DESCRIPTION("Misc driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-misc");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-misc");
 MODULE_VERSION(RT5025_DRV_VER);
index f93f742e962a4fe7459b588aca0ce2bb37a0a89a..f20a5fc493110b228054133b852708347ef05d78 100755 (executable)
@@ -64,6 +64,43 @@ config WM8350_POWER
           Say Y here to enable support for the power management unit
          provided by the Wolfson Microelectronics WM8350 PMIC.
 
+config CHARGER_RT5025
+       bool "RT5025 Charger Driver"
+       depends on MFD_RT5025
+       default n
+       help
+         Enable RT5025 Charger driver.
+
+config RT_POWER
+       bool "RT5025 PMIC cable report"
+       depends on CHARGER_RT5025
+       default n
+       help
+         Enable AC/USB report.
+
+config RT_SUPPORT_ACUSB_DUALIN
+       bool "RT AC/USB Dualin Option"
+       depends on RT_POWER
+       default n
+       help
+         Say Y here to enable dualin, otherwise
+         N is just singlein.
+
+config BATTERY_RT5025
+       bool "RT5025 PMIC ADC Type gauge driver"
+       depends on MFD_RT5025
+       default n
+       help
+         Enable the RT5025 ADC Fuelgauge driver.
+
+config RT_JEITA_REMOVE
+       bool "RT Jeita function remobe"
+       depends on CHARGER_RT5025 && BATTERY_RT5025
+       default n
+       help
+         Say Y here to remove Jeita function.
+
+
 config BATTERY_RICOH619
        tristate "Ricoh RC5T619 PMIC battery driver"
        depends on MFD_RICOH619 && I2C && GENERIC_HARDIRQS
index 0030e120ba7051048689b58b3bdd2fa4544fc8ae..b2f1409e0e901ca4435842a6a593c39e72c54e03 100755 (executable)
@@ -60,3 +60,6 @@ obj-$(CONFIG_BATTERY_RICOH619)        += ricoh619-battery.o
 obj-$(CONFIG_CHARGER_DISPLAY)          += rk29_charger_display.o
 obj-$(CONFIG_POWER_RESET)      += reset/
 obj-$(CONFIG_BATTERY_RK818)     += rk818_battery.o
+obj-$(CONFIG_CHARGER_RT5025)   += rt5025-charger.o
+obj-$(CONFIG_RT_POWER)         += rt-power.o
+obj-$(CONFIG_BATTERY_RT5025)   += rt5025-battery.o
diff --git a/drivers/power/rt-power.c b/drivers/power/rt-power.c
new file mode 100755 (executable)
index 0000000..22fc92c
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ *  drivers/power/rt-power.c
+ *  Driver for Richtek RT PMIC Power driver
+ *
+ *  Copyright (C) 2014 Richtek Technology Corp.
+ *  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; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+#include <linux/wakelock.h>
+
+#include <linux/power/rt-power.h>
+
+struct rt_power_info {
+       struct device *dev;
+       struct power_supply ac_psy;
+       struct power_supply usb_psy;
+       struct wake_lock usbdet_wakelock;
+       struct delayed_work usbdet_work;
+       int chg_volt;
+       int acchg_icc;
+       int usbtachg_icc;
+       int usbchg_icc;
+       unsigned char ac_online:1;
+       unsigned char usbta_online:1;
+       unsigned char usb_online:1;
+       unsigned char suspend:1;
+       unsigned char usbcnt;
+};
+
+#define RT_USBCNT_MAX 60
+
+static char *rtpower_supply_list[] = {
+       "battery",
+};
+
+static enum power_supply_property rtpower_props[] = {
+       POWER_SUPPLY_PROP_ONLINE,
+};
+
+static int rtpower_set_charger(struct rt_power_info *pi)
+{
+       struct power_supply *chg_psy;
+       union power_supply_propval pval;
+       int rc = 0, is_chg_on = 0;
+
+       chg_psy = power_supply_get_by_name("rt-charger");
+       if (chg_psy) {
+               rc = chg_psy->get_property(chg_psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+               if (rc < 0)
+                       dev_err(pi->dev, "get chg online prop fail\n");
+               else
+                       is_chg_on = pval.intval;
+               if (pi->ac_online) {
+                       pval.intval = pi->acchg_icc;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set acchg aicr fail\n");
+                       pval.intval = 500;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set acchg icc fail\n");
+                       pval.intval = POWER_SUPPLY_TYPE_MAINS;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charge cable fail\n");
+                       if (!is_chg_on) {
+                               pval.intval = pi->chg_volt;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set chg voltage fail\n");
+                               pval.intval = 1;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set charger online fail\n");
+                       }
+                       pval.intval = 1;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charger present fail\n");
+               } else if (pi->usbta_online) {
+                       pval.intval = pi->usbtachg_icc;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set usbtachg aicr fail\n");
+                       pval.intval = 500;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set usbtachg icc fail\n");
+                       pval.intval = POWER_SUPPLY_TYPE_USB_DCP;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charge cable fail\n");
+                       if (!is_chg_on) {
+                               pval.intval = pi->chg_volt;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set chg voltage fail\n");
+                               pval.intval = 1;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set charger online fail\n");
+                       }
+                       pval.intval = 1;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charger present fail\n");
+               } else if (pi->usb_online) {
+                       pval.intval = pi->usbchg_icc;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set usbchg aicr fail\n");
+                       pval.intval = 500;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set usbchg icc fail\n");
+                       pval.intval = POWER_SUPPLY_TYPE_USB;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charge cable fail\n");
+                       if (!is_chg_on) {
+                               pval.intval = pi->chg_volt;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set chg voltage fail\n");
+                               pval.intval = 1;
+                               rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
+                                       &pval);
+                               if (rc < 0)
+                                       dev_err(pi->dev, "set charger online fail\n");
+                       }
+                       pval.intval = 1;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_PRESENT,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charger present fail\n");
+
+               } else {
+                       pval.intval = 0;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_ONLINE,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charger online fail\n");
+                       pval.intval = 0;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CHARGE_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set charge cable fail\n");
+                       pval.intval = pi->chg_volt;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_VOLTAGE_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set chg voltage fail\n");
+                       pval.intval = 500;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_AVG,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set chg aicr fail\n");
+                       pval.intval = 500;
+                       rc = chg_psy->set_property(chg_psy, POWER_SUPPLY_PROP_CURRENT_NOW,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(pi->dev, "set chg icc fail\n");
+               }
+               power_supply_changed(chg_psy);
+       } else {
+               rc = -EINVAL;
+               dev_err(pi->dev, "cannot get rt-charger psy\n");
+       }
+       return rc;
+}
+
+static int rtpower_get_property(struct power_supply *psy, enum power_supply_property psp, \
+                       union power_supply_propval *val)
+{
+       struct rt_power_info *pi = dev_get_drvdata(psy->dev->parent);
+       int rc = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               if (psy->type == POWER_SUPPLY_TYPE_MAINS)
+                       val->intval = (pi->ac_online || pi->usbta_online)?1 : 0;
+               else if (psy->type == POWER_SUPPLY_TYPE_USB)
+                       val->intval = pi->usb_online;
+               else
+                       rc = -EINVAL;
+               break;
+       default:
+               rc = -EINVAL;
+               break;
+       }
+       return rc;
+}
+
+static int rtpower_set_property(struct power_supply *psy, enum power_supply_property psp, \
+                               const union power_supply_propval *val)
+{
+       struct rt_power_info *pi = dev_get_drvdata(psy->dev->parent);
+       int rc = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               if (psy->type == POWER_SUPPLY_TYPE_MAINS) {
+                       if (pi->ac_online != val->intval) {
+                               pi->ac_online = val->intval;
+                               rc = rtpower_set_charger(pi);
+                       }
+               } else if (psy->type == POWER_SUPPLY_TYPE_USB) {
+                       if (pi->usb_online != val->intval) {
+                               pi->usb_online = val->intval;
+                               if (val->intval) {
+                                       pi->usbcnt = 0;
+                                       wake_lock(&pi->usbdet_wakelock);
+                                       schedule_delayed_work(&pi->usbdet_work, 1*HZ);
+                               } else {
+                                       pi->usbcnt = RT_USBCNT_MAX;
+                                       schedule_delayed_work(&pi->usbdet_work, 0);
+                                       if (pi->usbta_online) {
+                                               pi->usbta_online = 0;
+                                               power_supply_changed(&pi->ac_psy);
+                                       }
+                               }
+                               rc = rtpower_set_charger(pi);
+                       }
+               } else {
+                               rc = -EINVAL;
+               }
+               break;
+       default:
+               rc = -EINVAL;
+               break;
+       }
+       return rc;
+}
+
+extern int dwc_otg_check_dpdm(bool wait);
+static void usbdet_work_func(struct work_struct *work)
+{
+       struct rt_power_info *pi = container_of(work, struct rt_power_info, \
+                       usbdet_work.work);
+       int usb_det = dwc_otg_check_dpdm(0);
+
+       switch (usb_det) {
+       case 2:
+               dev_info(pi->dev, "usb ta checked\n");
+               if (pi->usb_online) {
+                       pi->usbta_online = 1;
+                       rtpower_set_charger(pi);
+                       power_supply_changed(&pi->ac_psy);
+               }
+               pi->usbcnt = RT_USBCNT_MAX;
+               break;
+       case 1:
+       case 0:
+               dev_info(pi->dev, "normal usb\n");
+               break;
+       default:
+               break;
+       }
+       if (pi->usbcnt < RT_USBCNT_MAX) {
+               pi->usbcnt++;
+               schedule_delayed_work(&pi->usbdet_work, 1*HZ);
+       } else {
+               wake_unlock(&pi->usbdet_wakelock);
+       }
+}
+
+static int rt_power_probe(struct platform_device *pdev)
+{
+       struct rt_power_info *pi;
+       struct rt_power_data *rt_power_pdata = pdev->dev.platform_data;
+       int ret = 0;
+
+       pi = devm_kzalloc(&pdev->dev, sizeof(*pi), GFP_KERNEL);
+       if (!pi)
+               return -ENOMEM;
+       pi->dev = &pdev->dev;
+       wake_lock_init(&pi->usbdet_wakelock, WAKE_LOCK_SUSPEND, "rt-usb-det");
+       INIT_DELAYED_WORK(&pi->usbdet_work, usbdet_work_func);
+       pi->chg_volt = rt_power_pdata->chg_volt;
+       pi->acchg_icc = rt_power_pdata->acchg_icc;
+       pi->usbtachg_icc = rt_power_pdata->usbtachg_icc;
+       pi->usbchg_icc = rt_power_pdata->usbchg_icc;
+       platform_set_drvdata(pdev, pi);
+
+       /* ac power supply register*/
+       pi->ac_psy.name = RT_AC_NAME;
+       pi->ac_psy.type = POWER_SUPPLY_TYPE_MAINS;
+       pi->ac_psy.supplied_to = rtpower_supply_list;
+       pi->ac_psy.properties = rtpower_props;
+       pi->ac_psy.num_properties = ARRAY_SIZE(rtpower_props);
+       pi->ac_psy.get_property = rtpower_get_property;
+       pi->ac_psy.set_property = rtpower_set_property;
+       ret = power_supply_register(&pdev->dev, &pi->ac_psy);
+       if (ret < 0) {
+               dev_err(&pdev->dev, " create ac power supply fail\n");
+               goto err_init;
+       }
+       /*usb power supply register*/
+       pi->usb_psy.name = RT_USB_NAME;
+       pi->usb_psy.type = POWER_SUPPLY_TYPE_USB;
+       pi->usb_psy.supplied_to = rtpower_supply_list;
+       pi->usb_psy.properties = rtpower_props;
+       pi->usb_psy.num_properties = ARRAY_SIZE(rtpower_props);
+       pi->usb_psy.get_property = rtpower_get_property;
+       pi->usb_psy.set_property = rtpower_set_property;
+       ret = power_supply_register(&pdev->dev, &pi->usb_psy);
+       if (ret < 0) {
+               dev_err(&pdev->dev, " create usb power supply fail\n");
+               goto err_acpsy;
+       }
+       return 0;
+
+err_acpsy:
+       power_supply_unregister(&pi->ac_psy);
+err_init:
+       wake_lock_destroy(&pi->usbdet_wakelock);
+       return ret;
+}
+
+static int rt_power_remove(struct platform_device *pdev)
+{
+       struct rt_power_info *pi = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&pi->usb_psy);
+       power_supply_unregister(&pi->ac_psy);
+       wake_lock_destroy(&pi->usbdet_wakelock);
+       return 0;
+}
+
+static int rt_power_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct rt_power_info *pi = platform_get_drvdata(pdev);
+
+       pi->suspend = 1;
+       return 0;
+}
+
+static int rt_power_resume(struct platform_device *pdev)
+{
+       struct rt_power_info *pi = platform_get_drvdata(pdev);
+
+       pi->suspend = 0;
+       return 0;
+}
+
+static const struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt-power",},
+       {},
+};
+
+static struct platform_driver rt_power_driver = {
+       .driver = {
+               .name = "rt-power",
+               .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
+       },
+       .probe = rt_power_probe,
+       .remove = rt_power_remove,
+       .suspend = rt_power_suspend,
+       .resume = rt_power_resume,
+};
+static int rt_power_init(void)
+{
+       return platform_driver_register(&rt_power_driver);
+}
+subsys_initcall(rt_power_init);
+
+static void rt_power_exit(void)
+{
+       platform_driver_unregister(&rt_power_driver);
+}
+module_exit(rt_power_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("RT Power driver");
+MODULE_ALIAS("platform:rt-power");
+MODULE_VERSION("1.0.0_G");
old mode 100644 (file)
new mode 100755 (executable)
index f6a290e..08d6a06
@@ -2,12 +2,13 @@
  * I2C Driver for Richtek RT5025 PMIC
  * Multi function device - multi functional baseband PMIC Battery part
  *
- * Copyright (C) 2013
+ *  Copyright (C) 2014 Richtek Technology Corp.
  * 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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/kernel.h>
 #include <linux/workqueue.h>
 #include <linux/jiffies.h>
 #include <linux/timer.h>
-#include <linux/android_alarm.h>
+#include <linux/alarmtimer.h>
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-battery.h>
 
+
 #define VOLTAGE_ALERT 0
 #define TEMPERATURE_ALERT 0
 
 
 u8 irq_thres[LAST_TYPE];
 
-static int rt5025_battery_parameter_backup(struct rt5025_battery_info *);
+static unsigned char gauge_init_regval[] = {
+       0xFF, /*REG 0x53*/
+       0x00, /*REG 0x54*/
+       0x00, /*REG 0x55*/
+       0xFF, /*REG 0x56*/
+       0x00, /*REG 0x57*/
+};
 
-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;
-       bi->last_tp_flag = true;
-  }
-  else
-       power_supply_changed(&bi->battery);
-  wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
-  schedule_delayed_work(&bi->monitor_work, 0);
-}
-EXPORT_SYMBOL(rt5025_gauge_set_status);
+static u16 crctab16[256] = {
+       0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+       0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+       0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+       0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+       0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+       0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+       0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+       0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+       0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+       0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+       0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+       0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+       0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+       0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+       0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+       0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+       0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+       0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+       0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+       0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+       0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+       0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+       0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+       0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+       0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+       0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+       0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+       0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+       0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+       0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+       0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+       0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
+};
 
-void rt5025_gauge_set_online(struct rt5025_battery_info *bi, bool present)
-{
-  bi->online = present;
-}
-EXPORT_SYMBOL(rt5025_gauge_set_online);
+static int rt5025_battery_parameter_backup(struct rt5025_battery_info *);
+static void rt5025_get_external_temp(struct rt5025_battery_info *);
+static void rt5025_get_internal_temp(struct rt5025_battery_info *);
+static void rt5025_get_vcell(struct rt5025_battery_info *);
+static void rt5025_get_current(struct rt5025_battery_info *);
+static void rt5025_temp_comp(struct rt5025_battery_info *);
 
+/* 20140415 CY */
 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)
+static void rt5025_set_battery_led(struct rt5025_battery_info *bi, int status)
 {
-       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));
+       switch (status) {
+       case POWER_SUPPLY_STATUS_CHARGING:
+               break;
+       case POWER_SUPPLY_STATUS_DISCHARGING:
+               break;
+       case POWER_SUPPLY_STATUS_FULL:
+               break;
+       default:
+               break;
+       }
 }
 
-#if 0
-static void rt5025_run_time(struct rt5025_battery_info *bi)
+static int rt5025_set_property(struct power_supply *psy,\
+                       enum power_supply_property psp,\
+                       const union power_supply_propval *val)
 {
-       if(bi->curr <= 0)
-       {
-               bi->time_to_empty = bi->rm / (bi->curr*(-1));
+       struct rt5025_battery_info *bi = dev_get_drvdata(psy->dev->parent);
+       int rc = 0;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               if (val->intval == POWER_SUPPLY_STATUS_FULL) {
+                               bi->tp_flag = true;
+                               pr_info("%s: Battery is full \n", __func__);
+               } else {
+                               mutex_lock(&bi->status_change_lock);
+                               bi->status = val->intval;
+                               if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING)
+                                       bi->tp_flag = false;
+                               rt5025_set_battery_led(bi, bi->status);
+                               mutex_unlock(&bi->status_change_lock);
+                               }
+               wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
+               schedule_delayed_work(&bi->monitor_work, msecs_to_jiffies(100));
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               bi->batt_present = val->intval;
+               break;
+       default:
+               rc = -EINVAL;
+               break;
        }
-       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);
+       return rc;
 }
-#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;
+       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;
+               /*If there's no battery, always show battery health to good.*/
+               if (!bi->present || !bi->batt_present)
+                       val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               val->intval = bi->present;
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               if (val->intval == 23) {
+                       rt5025_get_external_temp(bi);
+                       val->intval = bi->ext_temp;
+               } else {
+                       /*If there's no battery, always show battery temperature to 25'c.*/
+                       if (!bi->present || !bi->batt_present)
+                               val->intval = 250;
+                       else
+                               val->intval = bi->ext_temp;
+               }
+               break;
+       case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+               rt5025_get_internal_temp(bi);
+               val->intval = bi->int_temp;
+               break;
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = bi->online;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               rt5025_get_vcell(bi);
+               val->intval = bi->vcell * 1000; /*uv*/
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               rt5025_get_current(bi);
+               val->intval = bi->curr * 1000; /*uA*/
+               break;
+       case POWER_SUPPLY_PROP_CAPACITY:
+               val->intval = bi->soc;
+               if (val->intval > 100)
+                       val->intval = 100;
+               /*If there's no battery, always show capacity to 50*/
+               if (!bi->present || !bi->batt_present)
+                       val->intval = 50;
+               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;
+               break;
+#endif
+       default:
+               return -EINVAL;
+       }
+       return 0;
 }
 
 static void rt5025_get_vcell(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-       
-  if (bi->init_once)
-  {
-    rt5025_clr_bits(bi->client, 0x07, 0x10);
-    RTINFO("set_current switch off\n");
-    mdelay(1000);
-  }
-
-  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->init_once)
-  {
-    rt5025_set_bits(bi->client, 0x07, 0x10);
-    RTINFO("set_current switch on\n");
-  }
+       u8 data[2];
 
-  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;
+       /* 20140415 CY */
+#if 0
+       if (bi->init_cap) {
+               rt5025_clr_bits(bi->client, 0x07, 0x10);
+               RTINFO("set_current switch off\n");
+               msleep(300);
+       }
+#endif /* #if 0 */
+       if (rt5025_read_reg(bi->client, RT5025_REG_VBATSH, data, 2) < 0)
+               pr_err("%s: Failed to read Voltage\n", __func__);
+       /* 20140415 CY */
+#if 0
+       if (bi->init_cap) {
+               rt5025_set_bits(bi->client, 0x07, 0x10);
+               RTINFO("set_current switch on\n");
+       }
+#endif /* #if 0 */
+       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 = 0;
+#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)
+       /* 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
+       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;
-  u8 curr_region;
+       u8 data[2];
+       s32 temp;
+       int sign = 0;
+       u8 curr_region;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_CURRH, data, 2) < 0)
+               pr_err("%s: Failed to read CURRENT\n", __func__);
 
-  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{
+       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)
+       if (temp < DEADBAND)
                temp = 0;
-  
-  if (sign){
-    temp *= -1;
-    bi->curr_raw *= -1;
+       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 = (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;
+       } else {
+                       temp = temp + bi->curr_offset;
        }
-
-  temp = (temp * 37375) / 100000; //Unit: 0.3125mA
-  if (temp < DEADBAND)
+       temp = (temp * 37375) / 100000; /*Unit: 0.3125mA*/
+       if (temp < DEADBAND)
                temp = 0;
-  
-  if (sign)
-    temp *= -1;
+       if (sign)
+               temp *= -1;
 #endif
 
-  if (bi->avg_flag) 
-    bi->curr = temp;
-  else
-         bi->curr = (bi->curr + temp) / 2;
-
-  if (bi->curr > -500)
-       curr_region = 0;
-  else if (bi->curr <= -500 && bi->curr > -1500)
-       curr_region = 1;
-  else
-       curr_region = 2;
-
-  if (curr_region != bi->edv_region)
-  {
-       switch (curr_region)
-       {
+       if (bi->avg_flag)
+               bi->curr = temp;
+       else
+               bi->curr = (bi->curr + temp) / 2;
+
+       if (bi->curr > -500)
+               curr_region = 0;
+       else if (bi->curr <= -500 && bi->curr > -1500)
+               curr_region = 1;
+       else
+               curr_region = 2;
+
+       if (curr_region != bi->edv_region) {
+               switch (curr_region) {
                case 0:
                        bi->empty_edv = rt5025_battery_param2[4].x;
                        break;
@@ -315,29 +331,30 @@ static void rt5025_get_current(struct rt5025_battery_info *bi)
                        bi->empty_edv = rt5025_battery_param2[4].x - 75;
                        break;
                case 2:
-                       bi->empty_edv = rt5025_battery_param2[4].x - 100 ;
+                       bi->empty_edv = rt5025_battery_param2[4].x - 100;
                        break;
-       }
+               }
        bi->edv_region = curr_region;
-  }
-  RTINFO("empty_voltage=%d\n", bi->empty_edv);
-
-  if(bi->curr > 0)
-  {
-    bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
-    bi->last_tp_flag = false;
-  }
-  else
-    bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
-  RTINFO("current=%d, internal_status=%d\n", bi->curr, bi->internal_status);
+       }
+       RTINFO("empty_voltage=%d\n", bi->empty_edv);
+
+       if (bi->curr > 0) {
+               bi->internal_status = POWER_SUPPLY_STATUS_CHARGING;
+               bi->last_tp_flag = false;
+               /*b. add fcc update flag; 2013/12/18*/
+               bi->fcc_update_flag = true;
+       } 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);
+       /*if (!bi->avg_flag)*/
+       /*pr_info("%d,",bi->curr);*/
 #else
-  if (bi->avg_flag)
+       if (bi->avg_flag)
                RTINFO("current_pre: %d\n", bi->curr);
-  else  
+       else
                RTINFO("current_avg: %d\n", bi->curr);
 #endif
 }
@@ -346,241 +363,228 @@ static void rt5025_get_internal_temp(struct rt5025_battery_info *bi)
 {
        u8 data[2];
        s32 temp;
-       if (rt5025_read_reg(bi->client, RT5025_REG_INT_TEMPERATUE_MSB, data, 2) < 0){
-               printk(KERN_ERR "%s: Failed to read internal TEMPERATURE\n", __func__);
-       }
 
-       temp = ((data[0]&0x1F)<<8) + data[1];
+       if (rt5025_read_reg(bi->client, RT5025_REG_INTEMPH, data, 2) < 0)
+               pr_err("%s: Failed to read internal TEMPERATURE\n", __func__);
+
+       temp = ((data[0] & 0x1F) << 8) + data[1];
        temp *= 15625;
        temp /= 100000;
 
-       temp = (data[0]&0x20)?-temp:temp;
+       temp = (data[0] & 0x20) ? -temp : temp;
        bi->int_temp = temp;
        RTINFO("internal temperature: %d\n", bi->int_temp);
 }
-       
+
 static void rt5025_get_external_temp(struct rt5025_battery_info *bi)
 {
-  u8 data[2];
-  s32 temp;
+       u8 data[2];
+       s32 temp;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_AINH, data, 2) < 0)
+               pr_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 (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) {
+       } 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->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;
+       } 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;
+               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;
+               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;
+               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__);
-  }
+{
+       u8 data[2];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNELH, data, 2) < 0)
+       pr_err("%s: failed to read channel\n", __func__);
 
-  if (mode == CHG)
+       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__);
-  }
+
+       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELH, 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=0;
-  
-  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];
-  RTINFO("qh_old=%d, ql_old=%d\n", qh_old, ql_old);
-  
-  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];
-  RTINFO("qh_new=%d, ql_new=%d\n", qh_new, ql_new);
+       u8 data[4];
+       u32 qh_old, ql_old, qh_new, ql_new;
+       u32 cc_masec, offset = 0;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QCHGHH, 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];
+       RTINFO("qh_old=%d, ql_old=%d\n", qh_old, ql_old);
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QCHGHH, 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];
+       RTINFO("qh_new=%d, ql_new=%d\n", qh_new, ql_new);
 
 #if RT5025_B
-  if (qh_new > qh_old){
-     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
-    }else {  
-      //cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
-     cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
+       if (qh_new > qh_old) {
+       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old) {
+                       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+                       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+               } else {
+                       /*cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;*/
+                       cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
-  }    
-  
-  if (!bi->init_once)
-       offset = bi->curr_offset * bi->time_interval;
-                         
-  if (cc_masec > offset){
+       }
+
+       if (!bi->init_once)
+               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;
        }
-#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){
+
+       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
 
-       //if (!bi->init_once)
-               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);
+       /*if (!bi->init_once)*/
+       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=0;
-  
-  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];
-  
+       u8 data[4];
+       u32 qh_old, ql_old, qh_new, ql_new;
+       u32 cc_masec, offset = 0;
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_QDCHGHH, data, 4) < 0)
+               pr_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_QDCHGHH, data, 4) < 0)
+               pr_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;
-     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
-  }else if (qh_new == qh_old){
-    if (ql_new >= ql_old){
-     //cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;
-     cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
-    }else {  
-     //cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;
-     cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
+       if (qh_new > qh_old) {
+               /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+               cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+       } else if (qh_new == qh_old) {
+               if (ql_new >= ql_old) {
+                       /*cc_masec = (((qh_new<<16) + ql_new) * 50134) / 10;*/
+                       cc_masec = qh_new*328558+(qh_new*1824+ql_new*50134)/10000;
+               } else {
+                       /*cc_masec = (((qh_old<<16) + ql_old) * 50134) / 10;*/
+                       cc_masec = qh_old*328558+(qh_old*1824+ql_old*50134)/10000;
                }
-  }    
-  
-  if (!bi->init_once)
-       offset = bi->curr_offset * bi->time_interval;
-                         
-  if (cc_masec != 0){
+       }
+       if (!bi->init_once)
+               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;
        }
-#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){
+
+       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;
-       if (bi->last_tp_flag)
+       /*b. add fcc update flag; 2013/12/18*/
+       if ((bi->last_tp_flag) && (bi->fcc_update_flag))
                bi->cal_fcc += cc_masec;
        else
                bi->cal_fcc = 0;
-       RTINFO("bi->cal_fcc=%d, bi->last_tp_flag=%d\n", bi->cal_fcc, bi->last_tp_flag);
-       //bi->dchg_cc = (cc_masec + bi->dchg_cc_unuse) / 3600;
-  //bi->dchg_cc_unuse = (cc_masec + bi->dchg_cc_unuse) % 3600;
+
+       RTINFO("bi->cal_fcc=%d, bi->last_tp_flag=%d\n",
+               bi->cal_fcc, bi->last_tp_flag);
+       /*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)){
+       if (bi->acc_dchg_cap >= (bi->dc * 3600)) {
                bi->cycle_cnt++;
                bi->acc_dchg_cap -= (bi->dc * 3600);
        }
@@ -589,113 +593,118 @@ static void rt5025_cycle_count(struct rt5025_battery_info *bi)
 static void rt5025_get_irq_flag(struct rt5025_battery_info *bi, u8 flag)
 {
 #if 0
-  u8 data[1];
+       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__);
-  }
+       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);
+       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;
+       u8 data[2];
+
+       if (rt5025_read_reg(bi->client, RT5025_REG_TIMERH, 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);
+       /*pr_info("%d,%d,", bi->gauge_timer,bi->time_interval);*/
 #else
-       RTINFO("timer %d , interval %d\n", bi->gauge_timer,bi->time_interval);
+       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)
+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;
+       if (rt5025_read_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0)
+               pr_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;
+       } 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)
+       if (rt5025_write_reg(bi->client, RT5025_REG_IRQCTL, data, 1) < 0)
                pr_err("%s: failed to write IRQ control\n", __func__);
 }
 
@@ -703,28 +712,21 @@ 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__); 
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMAX, data, 1) < 0)
+               pr_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__);        
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMIN1, data, 1) < 0)
+               pr_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__);        
+       if (rt5025_write_reg(client, RT5025_REG_VALRTMIN2, data, 1) < 0)
+               pr_err("%s: failed to write VALRT MIN2 threshold\n",
+                       __func__);
 }
 
 static void rt5025_alert_init(struct rt5025_battery_info *bi)
@@ -733,115 +735,146 @@ 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);     
+       rt5025_alert_setting(bi, MINVOLT2, VOLTAGE_ALERT);
 }
 
-void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, u8 irq_flag)
+void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi,
+       unsigned int irq_flag)
 {
-  rt5025_get_irq_flag(bi, 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);
+       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_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);
+       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);
+       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);
+       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);
-       wake_lock_timeout(&bi->status_wake_lock, 1.5*HZ);
-       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;
+       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;
+{
+       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++;
-  }
+       int i = 1;
+       int size;
+       int slope, const_term;
+       int delta_y, delta_x;
 
-  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);
+       size = ARRAY_SIZE(rt5025_battery_param1);
+       while ((bi->vcell < rt5025_battery_param1[i].x) &&
+               (i < (size - 1))) {
+               i++;
+       }
 
-  slope = delta_y  * 1000 / delta_x;
+       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);
 
-  const_term = (rt5025_battery_param1[i].y) - ((rt5025_battery_param1[i].x * slope) / 1000);
+       slope = delta_y  * 1000 / delta_x;
 
-  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;
+       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;
 
-  rt5025_battery_parameter_backup(bi);
+       rt5025_battery_parameter_backup(bi);
 
-  //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;              
+       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->tp_flag == 1) &&
-           (bi->soc < 100))
-       {
-               bi->soc++;
+       if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING || bi->tp_flag) &&
+           (bi->soc < 100)) {
+               if (bi->last_suspend  == true) {
+                       bi->soc = 100;
+                       bi->last_suspend = false;
+               } else {
+                       bi->soc++;
+               }
                bi->rm = bi->fcc * bi->soc * 36;
                rt5025_convert_masec_to_permille(bi);
-       }
-       else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
-                 (bi->soc > 0))
-       {
-               bi->soc--;
+
+               if (bi->soc == 100) {
+                       /*fcc update in soc smooth 100%.*/
+                       if (bi->cal_soc_offset != 0) {
+                               bi->fcc_aging -= bi->cal_soc_offset;
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->soc * 36;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_soc_offset = 0;
+                       }
+                       wake_unlock(&bi->smooth100_wake_lock);
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+
+                       /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/
+                       bi->last_tp_flag = true;
+                       mutex_lock(&bi->status_change_lock);
+                       if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                               bi->status = POWER_SUPPLY_STATUS_FULL;
+                               rt5025_set_battery_led(bi, bi->status);
+                       }
+                       mutex_unlock(&bi->status_change_lock);
+               }
+       } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+               (bi->soc > 0)) {
+               if (bi->last_suspend  == true) {
+                       bi->soc = 0;
+                       bi->last_suspend = false;
+               } else {
+                       bi->soc--;
+               }
                bi->rm = bi->fcc * bi->soc * 36;
                rt5025_convert_masec_to_permille(bi);
-       }
-       else
-       {
+               if (bi->soc == 0)
+                       wake_unlock(&bi->smooth0_wake_lock);
+       } else {
          bi->smooth_flag = false;
          bi->update_time = NORMAL_POLL;
   }
@@ -850,343 +883,289 @@ static void rt5025_smooth_soc(struct rt5025_battery_info *bi)
 
 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->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) && 
-                                               (bi->tp_flag == 0))
-               {
-                       if (bi->soc > bi->pre_soc) 
+               } else if ((bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+                                               (bi->tp_flag == 0)) {
+                       if (bi->soc > bi->pre_soc)
                                bi->soc = bi->pre_soc;
                }
-       }
-       else
+       } else {
                bi->init_once = false;
+       }
 
        if (bi->pre_soc != bi->soc)
                rt5025_battery_parameter_backup(bi);
 
        bi->pre_soc = bi->soc;
-       RTINFO("pre_soc=%d, soc=%d, internal status=%d\n", bi->pre_soc,bi->soc,bi->internal_status);
+       RTINFO("pre_soc=%d, soc=%d, internal status=%d\n",
+               bi->pre_soc, bi->soc, bi->internal_status);
 }
 
 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) 
-  {
-       if (bi->tp_flag)
-               bi->soc = 100;
-               else if(bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)
-               {
-                               bi->soc = 99;
-                               bi->pre_soc = 99;
+        /*lock 99%*/
+       u16 eoc_fcc_new  = 0;
+
+       RTINFO("internal status=%d, tp_flag=%d, soc=%d, soc99_lock_cnt=%d\n",
+               bi->internal_status, bi->tp_flag, bi->soc,
+               bi->soc99_lock_cnt);
+       RTINFO("init_once=%d, rm=%d, soc=%d\n",
+               bi->init_once, bi->rm, bi->soc);
+
+       if (bi->soc >= 99) {
+               if (bi->soc99_lock_cnt >= 3600) {
+                       bi->soc = 100;
+                       bi->permille = 1000;
+                       /*eoc fcc update function: when flag is true, update FCC.*/
+                       if (bi->cal_eoc_fcc != 0) {
+                               /*eoc fcc update function: fcc update limitation 3%*/
+                               eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc / 3600;
+                               if (eoc_fcc_new > ((bi->fcc_aging * 103) / 100))
+                                       bi->fcc_aging = (bi->fcc_aging * 103) / 100;
+                               else
+                                       bi->fcc_aging = eoc_fcc_new;
+
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                                       }
+                               bi->cal_eoc_fcc = 0;
+                       }
+                       wake_unlock(&bi->full_battery_wake_lock);
+                       bi->soc99_lock_cnt = 0;
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+                       /*b. add fcc update flag; 2013/12/18*/
+                       bi->fcc_update_flag = false;
+
+                       /*a. When SOC = 100, report battery status is full; 2013/12/17
+                       bi->status = POWER_SUPPLY_STATUS_FULL;
+                       */
+               } else if (bi->tp_flag) {
+                       RTINFO("before_eoc_fcc_new=%d\n", eoc_fcc_new);
+                       RTINFO("before_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
+                       RTINFO("before_fcc_aging=%d\n", bi->fcc_aging);
+                       bi->soc = 100;
+                       bi->permille = 1000;
+                       if (bi->cal_eoc_fcc != 0) {
+                               /*fcc update in eoc occurs. */
+                               eoc_fcc_new = bi->fcc_aging + bi->cal_eoc_fcc/3600;
+                               if (eoc_fcc_new > ((bi->fcc_aging*103)/100))
+                                       bi->fcc_aging = (bi->fcc_aging*103)/100;
+                               else
+                                       bi->fcc_aging = eoc_fcc_new;
+
+                               RTINFO("after_eoc_fcc_new=%d\n", eoc_fcc_new);
+                               RTINFO("after_cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
+                               RTINFO("after_fcc_aging=%d\n", bi->fcc_aging);
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_eoc_fcc = 0;
+                       } else if (bi->cal_soc_offset != 0) {
+                               bi->fcc_aging -= bi->cal_soc_offset;
+                               if ((200 <= bi->ext_temp) && (bi->ext_temp <= 300)) {
+                                       bi->fcc = bi->fcc_aging;
+                                       bi->rm = bi->fcc * bi->permille * 36 / 10;
+                               } else {
+                                       rt5025_temp_comp(bi);
+                               }
+                               bi->cal_soc_offset = 0;
+                       }
+
+                       wake_unlock(&bi->full_battery_wake_lock);
+                       bi->soc99_lock_cnt = 0;
+                       bi->last_tp = true;
+                       bi->tp_flag = false;
+                       bi->pre_soc = bi->soc;
+
+                       /*c. Only EOC occurs and full discharge to update FCC; 2013/12/17*/
+                       bi->last_tp_flag = true;
+
+                       mutex_lock(&bi->status_change_lock);
+                       if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                               bi->status = POWER_SUPPLY_STATUS_FULL;
+                               rt5025_set_battery_led(bi, bi->status);
+                       }
+                       mutex_unlock(&bi->status_change_lock);
+               } else if ((bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)  &&
+                                               (bi->last_tp == false)) {
+                       bi->soc = 99;
+                       bi->pre_soc = 99;
+                       bi->soc99_lock_cnt += bi->time_interval;
                }
-  }
-  else if ((bi->soc < 99) && (bi->tp_flag))
-  {
-               if (!bi->last_suspend)
-               {
-                       bi->update_time = SMOOTH_POLL;
-                       bi->smooth_flag = true;
-                       rt5025_smooth_soc(bi);
+       } else if ((bi->soc < 99) && (bi->tp_flag)) {
+               /*calculate soc offset */
+               if (bi->cal_soc_offset == 0) {
+                       bi->cal_soc_offset = bi->fcc*3600 - bi->rm;
+                       if (bi->cal_soc_offset > (bi->fcc_aging*3/100))
+                               bi->cal_soc_offset = bi->fcc_aging*3/100;
                }
-               else
-                       bi->last_suspend=false;
-  }
-  else
-  {
+               wake_lock(&bi->smooth100_wake_lock);
+               bi->update_time = SMOOTH_POLL;
+               bi->smooth_flag = true;
+               rt5025_smooth_soc(bi);
+       } else {
+               wake_unlock(&bi->smooth100_wake_lock);
                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;
-                       bi->pre_soc = 1; 
+               bi->soc99_lock_cnt = 0;
+       }
+               /* a. When SOC = 100, report battery status is full; 2013/12/17
+               /// a. judge charging status to check battery full condition; 2013/12/18*/
+       if ((bi->soc == 100) &&
+               (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)) {
+               mutex_lock(&bi->status_change_lock);
+               if (bi->status != POWER_SUPPLY_STATUS_DISCHARGING) {
+                       bi->status = POWER_SUPPLY_STATUS_FULL;
+                       rt5025_set_battery_led(bi, bi->status);
                }
-      
-       }else if ((bi->soc > 1) &&
-            (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
-            (bi->edv_flag)){
-               if (!bi->last_suspend)
-               {
-                       bi->update_time = SMOOTH_POLL;
-                       bi->smooth_flag = true;
-                       rt5025_smooth_soc(bi);
+               mutex_unlock(&bi->status_change_lock);
+       }
+
+       /*lock 1%   */
+       if ((bi->soc <= 1) &&
+         (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING)) {
+               if (bi->edv_flag) {
+                       bi->soc = 0;
+               } else {
+                       if (bi->rm <= 0) {
+                               bi->soc1_lock_cnt += bi->time_interval;
+                               if (bi->soc1_lock_cnt >= 600) {
+                                       bi->soc = 0;
+                                       bi->soc1_lock_cnt = 0;
+                               } else {
+                                       bi->soc = 1;
+                                       bi->pre_soc = 1;
+                               }
+                       } else {
+                               bi->soc = 1;
+                               bi->pre_soc = 1;
+                               bi->soc1_lock_cnt = 0;
+                       }
                }
-               else
-                       bi->last_suspend=false;
-       }else{
+       } else if ((bi->soc > 1) &&
+               (bi->internal_status == POWER_SUPPLY_STATUS_DISCHARGING) &&
+                       (bi->edv_flag)) {
+               wake_lock(&bi->smooth0_wake_lock);
+               bi->update_time = SMOOTH_POLL;
+               bi->smooth_flag = true;
+               rt5025_smooth_soc(bi);
+       } else {
                bi->edv_flag = false;
+               wake_unlock(&bi->smooth0_wake_lock);
        }
+       RTINFO("cal_soc_offset=%d\n", bi->cal_soc_offset);
 }
 
 static void rt5025_get_soc(struct rt5025_battery_info *bi)
 {
-  if (bi->smooth_flag){
-    bi->smooth_flag = false;
-    bi->update_time = NORMAL_POLL;
-  }
+       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->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;
+                       bi->rm = bi->fcc * 3600;
+
+               /* accumulate coulomb counter when rm = fcc and enable flag = true.*/
+               if (bi->rm == (bi->fcc * 3600))
+                       bi->cal_eoc_fcc += (bi->chg_cc - bi->dchg_cc);
+               else
+                       bi->cal_eoc_fcc = 0;
+
+               RTINFO("cal_eoc_fcc=%d\n", bi->cal_eoc_fcc);
                rt5025_convert_masec_to_permille(bi);
+               /*a. When SOC = 100, report battery status is full; 2113/12/17*/
                bi->soc = DIV_ROUND_UP(bi->permille, 10);
+       }
 #if RT5025_CSV
-    bi->temp_soc = bi->soc;
-    //pr_info("%d", bi->soc);
+       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);
+       RTINFO("temp_soc=%d\n", bi->soc);
 #endif
-  }
 #if RT5025_CSV
-       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n", bi->soc,bi->permille,bi->rm,bi->fcc,bi->smooth_flag);
- // 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);
+       RTINFO("soc=%d, permille=%d, rm=%d, fcc=%d, smooth_flag=%d\n",
+               bi->soc, bi->permille, bi->rm,
+               bi->fcc, bi->smooth_flag);
+       /*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;
+       /*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)
-       {
+
+       if (bi->tp_flag == true) {
                bi->rm = bi->fcc * 3600;
                rt5025_convert_masec_to_permille(bi);
                bi->update_time = NORMAL_POLL;
        }
 
-       if (bi->vcell <= bi->empty_edv)
-       {
+       if (bi->vcell <= bi->empty_edv) {
                if (bi->edv_cnt < 2)
                        bi->edv_cnt++;
+       } else {
+               bi->edv_cnt = 0;
        }
-       else
-               bi->edv_cnt=0;
-       
-       if(bi->empty_edv < bi->vcell && bi->vcell <= bi->empty_edv+300)
-       {
+
+       if (bi->empty_edv < bi->vcell && bi->vcell <= bi->empty_edv + 300) {
                bi->update_time = EDV_POLL;
                bi->edv_detection = true;
-       }
-       else if((bi->vcell >= bi->empty_edv + 300 +EDV_HYS) && (bi->edv_detection == true))
-       {
+       } else if ((bi->vcell >= bi->empty_edv + 300 + EDV_HYS)
+               && (bi->edv_detection == true)) {
                 bi->update_time = NORMAL_POLL;
-                bi->edv_detection = false;              
-       }
-       else if((bi->vcell <= bi->empty_edv && bi->edv_cnt == 2)) //&& (bi->min_volt2_alert == true))
-       {
+                bi->edv_detection = false;
+       } else if ((bi->vcell <= bi->empty_edv && bi->edv_cnt == 2)) {
                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 > bi->empty_edv + EDV_HYS)) //&& (bi->min_volt2_alert == true))
-       {
+       } else if ((bi->vcell > bi->empty_edv + EDV_HYS)) {
                bi->min_volt2_alert = false;
                bi->edv_flag = 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;
+
+       if (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING)
                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;
-  if (bi->status != POWER_SUPPLY_STATUS_FULL)
-    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;
-}
-
-#if 0
-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__);
-  }
-}
+#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
 
-#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__);
-  }
+ /* return;*/
 }
-#endif
 
-static u16 get_crc16_value(u8data, int size)
+static u16 get_crc16_value(u8 *data, int size)
 {
        u16 fcs = 0xffff;
        int len = size;
        int i = 0;
        u16 temp = 0;
 
-       while (len > 0)
-       {
-               fcs = (u16)((fcs>>8)^crctab16[(fcs^data[i])&0xff]);
+       while (len > 0) {
+               fcs = (u16)((fcs >> 8) ^ crctab16[(fcs ^ data[i]) & 0xff]);
                len--;
                i++;
        }
@@ -1194,15 +1173,14 @@ static u16 get_crc16_value(u8* data, int size)
        return temp;
 }
 
-static int IsCrc16Good(u8data, int size)
+static int IsCrc16Good(u8 *data, int size)
 {
        u16 fcs = 0xffff;
        int len = size;
        int i = 0;
 
-       while (len>0)
-       {
-               fcs = (u16)((fcs>>8)^crctab16[((fcs^data[i])&0xff)]);
+       while (len > 0) {
+               fcs = (u16)((fcs >> 8) ^ crctab16[((fcs ^ data[i]) & 0xff)]);
                len--;
                i++;
        }
@@ -1212,76 +1190,66 @@ static int IsCrc16Good(u8* data, int size)
 static int rt5025_battery_parameter_backup(struct rt5025_battery_info *bi)
 {
        u16 crc_value = 0;
-       u8 data[12]= {0};
+       u8 data[15] = {0};
+
        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[0], 2);
-       //acc_dchg_cap
-       data[2] = (bi->acc_dchg_cap>>24)&0xff;
-       data[3] = (bi->acc_dchg_cap>>16)&0xff;
-       data[4] = (bi->acc_dchg_cap>>8)&0xff;
-       data[5] = (bi->acc_dchg_cap)&0xff;
-       rt5025_write_reg(bi->client, 0x23, &data[2], 4);
-       //cycle_count
-       data[6] = (bi->cycle_cnt)&0xff;
-       rt5025_write_reg(bi->client, 0x27, &data[6], 1);
-       //soc
-       data[7] = (bi->soc)&0xff;
-       rt5025_write_reg(bi->client, 0x28, &data[7], 1);
-       //gauge_timer
-       data[8] = (bi->pre_gauge_timer>>8)&0xff;
-       data[9] = bi->pre_gauge_timer&0xff;
-       rt5025_write_reg(bi->client, 0x29, &data[8], 2);
-       //CRC value
-       crc_value = get_crc16_value(data, 10);
-       data[10] = crc_value&0xff;
-       data[11] = (crc_value>>8)&0xff;
-       rt5025_write_reg(bi->client, 0x2b, &data[10], 2);
+       /*backup fcc_aging, rm, cycle_count, acc_dchg_cap*/
+       /*fcc_aging*/
+       data[0] = (bi->fcc_aging >> 8) & 0xff;
+       data[1] = (bi->fcc_aging) & 0xff;
+       /*acc_dchg_cap*/
+       data[2] = (bi->acc_dchg_cap >> 24) & 0xff;
+       data[3] = (bi->acc_dchg_cap >> 16) & 0xff;
+       data[4] = (bi->acc_dchg_cap >> 8) & 0xff;
+       data[5] = (bi->acc_dchg_cap) & 0xff;
+       /*cycle_count*/
+       data[6] = (bi->cycle_cnt) & 0xff;
+       /*soc*/
+       data[7] = (bi->permille >> 8) & 0xff;
+       data[8] = (bi->permille) & 0xff;
+       /*gauge_timer*/
+       data[9] = (bi->pre_gauge_timer >> 8) & 0xff;
+       data[10] = bi->pre_gauge_timer & 0xff;
+       /*CRC value*/
+       crc_value = get_crc16_value(data, 13);
+       data[13] = crc_value & 0xff;
+       data[14] = (crc_value >> 8) & 0xff;
+       rt5025_write_reg(bi->client, RT5025_REG_RESV1, data, 15);
        return 0;
 }
 
 static int rt5025_battery_parameter_restore(struct rt5025_battery_info *bi)
 {
-       u8 data[4];
+       u8 data[15];
+
        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];
-       //acc_dchg_cap
-       rt5025_read_reg(bi->client, 0x23, data, 4);
-       bi->acc_dchg_cap = data[0]<<24 | data[1]<<16 | data[2]<<8 | data[3];
-       //cycle_count
-       rt5025_read_reg(bi->client, 0x27, data, 1);
-       bi->cycle_cnt = data[0];
-       //soc
-       rt5025_read_reg(bi->client, 0x28, data, 1);
-       bi->soc = bi->pre_soc = data[0];
-       //pre_gauge_timer
-       rt5025_read_reg(bi->client, 0x29, data, 2);
-       bi->pre_gauge_timer = bi->gauge_timer = (data[0]<<8) + data[1];
-       
+       rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15);
+       /*restore fcc_aging, rm ,cycle_count, acc_dchg_cap*/
+       /*fcc_aging*/
+       bi->fcc = bi->fcc_aging = data[0] << 8 | data[1];
+       /*acc_dchg_cap*/
+       bi->acc_dchg_cap = data[2] << 24 | data[3] << 16 | data[4] << 8 | data[5];
+       /*cycle_count*/
+       bi->cycle_cnt = data[6];
+       /*soc*/
+       bi->permille = data[7] << 8 | data[8];
+       /*pre_gauge_timer*/
+       bi->pre_gauge_timer = bi->gauge_timer = (data[9] << 8) + data[10];
+
        return 0;
 }
 
-
-// return value; 1-> initialized, 0-> no initial value
+/*return value; 1-> initialized, 0-> no initial value*/
 static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
 {
-       u8 data[12] = {0};
+       u8 data[15] = {0};
        int ret = 0;
 
-       if (rt5025_read_reg(bi->client, 0x21, data, 12)<0)
-       {
+       if (rt5025_read_reg(bi->client, RT5025_REG_RESV1, data, 15) < 0) {
                pr_err("%s: check initial value error\n", __func__);
                return 0;
-       }
-       else
-       {
-               ret = IsCrc16Good(data, 12);
+       } else {
+               ret = IsCrc16Good(data, 15);
        }
        RTINFO("initial check = %d\n", ret);
 
@@ -1289,19 +1257,19 @@ static int rt5025_battery_parameter_initcheck(struct rt5025_battery_info *bi)
 }
 
 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){
+       if (rt5025_read_reg(bi->client, RT5025_REG_CHANNELL, data, 1) < 0)
                pr_err("%s: failed to read channel\n", __func__);
-       }
+
        RTINFO("initial change enable=%02x\n", data[0]);
        data[0] = data[0] | CHANNEL_L_BIT_CADC_EN | CHANNEL_L_BIT_AINCH | \
                CHANNEL_L_BIT_VBATSCH | CHANNEL_L_BIT_VADC_EN | CHANNEL_L_BIT_INTEMPCH;
-       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNEL_LSB, data, 1) < 0){
+       if (rt5025_write_reg(bi->client, RT5025_REG_CHANNELL, 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;
@@ -1310,9 +1278,10 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
        bi->dchg_cc_unuse = 0;
        bi->pre_gauge_timer = 0;
        bi->online = 1;
+       bi->batt_present = 1;
        bi->status = bi->internal_status = POWER_SUPPLY_STATUS_DISCHARGING;
        bi->health = POWER_SUPPLY_HEALTH_GOOD;
-       
+
        bi->init_cap = true;
        bi->avg_flag = true;
 
@@ -1328,19 +1297,22 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
 
        bi->tp_cnt = 0;
        bi->tp_flag = false;
-  
+
        bi->acc_dchg_cap = 0;
        bi->cycle_cnt = 0;
        bi->empty_edv = rt5025_battery_param2[4].x;
        bi->edv_region = 0;
+       bi->soc1_lock_cnt = 0;
+       /*eoc fcc update function: initial variable.  */
+       bi->cal_eoc_fcc = 0;
+       bi->cal_soc_offset = 0;
 
-       // if has initial data, rewrite to the stored data
-       if (rt5025_battery_parameter_initcheck(bi))
-       {
+
+       /*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->rm = bi->soc*bi->fcc_aging*36;
+               bi->rm = bi->permille*bi->fcc_aging * 36 / 10;
        }
 
        bi->update_time = NORMAL_POLL;
@@ -1350,297 +1322,307 @@ static void rt5025_register_init(struct rt5025_battery_info *bi)
 
 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;
+       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);
+       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++;
-  }
+       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;              
+       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->permille * 36 / 10;
+       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);
+       RTINFO("soc->%d++\n", bi->soc);
+       bi->temp_range_0_5 = 0;
+       bi->temp_range_5_10 = 0;
+       bi->temp_range_10_15 = 0;
+       bi->temp_range_15_20 = 0;
+       bi->temp_range_20_30 = 0;
+       bi->temp_range_30_35 = 0;
+       bi->temp_range_35_40 = 0;
+       bi->temp_range_40_45 = 0;
+       bi->temp_range_45_50 = 0;
+
+       if (bi->ext_temp < 50)
+               bi->temp_range_0_5 = 1;
+       else if (50 <= bi->ext_temp && bi->ext_temp < 100)
+               bi->temp_range_5_10 = 1;
+       else if (100 <= bi->ext_temp && bi->ext_temp < 150)
+               bi->temp_range_10_15 = 1;
+       else if (150 <= bi->ext_temp && bi->ext_temp < 200)
+                       bi->temp_range_15_20 = 1;
+       else if (200 <= bi->ext_temp && bi->ext_temp <= 300)
+               bi->temp_range_20_30 = 1;
+       else if (300 < bi->ext_temp && bi->ext_temp <= 350)
+               bi->temp_range_30_35 = 1;
+       else if (350 < bi->ext_temp && bi->ext_temp <= 400)
+               bi->temp_range_35_40 = 1;
+       else if (400 < bi->ext_temp && bi->ext_temp <= 450)
+               bi->temp_range_40_45 = 1;
+       else if (450 < bi->ext_temp)
+               bi->temp_range_45_50 = 1;
+
+       if ((bi->temp_range_0_5 == 1) && (bi->range_0_5_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 1;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_5_10 == 1)
+               && (bi->range_5_10_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 1;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_10_15 == 1)
+               && (bi->range_10_15_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 1;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_15_20 == 1)
+               && (bi->range_15_20_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 1;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_20_30 == 1)
+               && (bi->range_20_30_done == 0)) {
+               bi->fcc = bi->fcc_aging;
+               bi->rm = bi->fcc * bi->permille * 36 / 10;
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 1;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_30_35 == 1)
+               && (bi->range_30_35_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 1;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_35_40 == 1)
+               && (bi->range_35_40_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 1;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_40_45 == 1)
+               && (bi->range_40_45_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 1;
+               bi->range_45_50_done = 0;
+       } else if ((bi->temp_range_45_50 == 1)
+               && (bi->range_45_50_done == 0)) {
+               rt5025_temp_comp(bi);
+               bi->range_0_5_done = 0;
+               bi->range_5_10_done = 0;
+               bi->range_10_15_done = 0;
+               bi->range_15_20_done = 0;
+               bi->range_20_30_done = 0;
+               bi->range_30_35_done = 0;
+               bi->range_35_40_done = 0;
+               bi->range_40_45_done = 0;
+               bi->range_45_50_done = 1;
+       }
+       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 internal temperature */
-  rt5025_get_internal_temp(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
-  }
+       int batt_type = 1;
+       /* Update voltage */
+       rt5025_get_vcell(bi);
+       /* Update current */
+       rt5025_get_current(bi);
+       /* Update internal temperature */
+       rt5025_get_internal_temp(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);                                         
+       /* Update SOC */
+       rt5025_get_soc(bi);
+
+       /* SOC Control Process */
+       rt5025_soc_lock(bi);
+       rt5025_soc_irreversible(bi);
+
+       if (bi->soc <= 99)
+               bi->last_tp = false;
+
+       if (rt5025_battery_param1[0].x >= 4250)
+               batt_type = 0;
+       else if (rt5025_battery_param1[0].x >= 4100)
+               batt_type = 1;
+
+       switch (batt_type) {
+       case 0:
+                       if ((bi->vcell >= 4250) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
+                               wake_lock(&bi->full_battery_wake_lock);
+                       else
+                               wake_unlock(&bi->full_battery_wake_lock);
+               break;
+       case 1:
+       default:
+                       if ((bi->vcell >= 4100) && (bi->internal_status == POWER_SUPPLY_STATUS_CHARGING))
+                               wake_lock(&bi->full_battery_wake_lock);
+                       else
+                               wake_unlock(&bi->full_battery_wake_lock);
+               break;
+       }
+
+       /* Update RTTF or RTTE */
+
+#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 VOLTAGE_ALERT
        if ((bi->min_volt2_irq == false) &&
-                               (bi->vcell > (bi->empty_edv + EDV_HYS))){       
-               rt5025_alert_setting(bi,MINVOLT2,true);                                         
-       }
+               (bi->vcell > (bi->empty_edv + EDV_HYS)))
+               rt5025_alert_setting(bi, MINVOLT2, true);
 #endif
+       bi->last_suspend = false;
 #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);
+       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
-  RTINFO("[RT5025] update_time=%d\n",bi->update_time);
-  RTINFO("\n");
+       RTINFO("[RT5025] update_time=%d\n", bi->update_time);
+       RTINFO("\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);
+       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;
 
-       wake_lock(&bi->monitor_wake_lock);      
+       wake_lock(&bi->monitor_wake_lock);
        rt5025_update(bi);
        power_supply_changed(&bi->battery);
-  
+
        /* 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);
@@ -1649,69 +1631,86 @@ static void rt5025_update_work(struct work_struct *work)
 }
 
 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
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_TEMP_AMBIENT,
+       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_sleepvth_setting(struct rt5025_battery_infobi)
+static int rt5025_battery_sleepvth_setting(struct rt5025_battery_info *bi)
 {
        u32 temp;
        u8 vmax_th, vmin_th;
        u8 vbat[2];
+
        RTINFO("\n");
-       rt5025_read_reg(bi->client, RT5025_REG_VCELL_MSB, vbat, 2);
-       temp = ((vbat[0]<<8) + vbat[1])*61;
-       vmax_th = (temp+5000)/1953;
-       vmin_th = (temp-5000)/1953;
+       rt5025_read_reg(bi->client, RT5025_REG_VBATSH, vbat, 2);
+       temp = ((vbat[0] << 8) + vbat[1]) * 61;
+       vmax_th = (temp + 5000) / 1953;
+       vmin_th = (temp - 5000) / 1953;
 
-       rt5025_write_reg(bi->client, RT5025_REG_VALRT_MAXTH, &vmax_th, 1);
-       rt5025_write_reg(bi->client, RT5025_REG_VALRT_MIN1TH, &vmin_th, 1);
+       rt5025_write_reg(bi->client, RT5025_REG_VALRTMAX, &vmax_th, 1);
+       rt5025_write_reg(bi->client, RT5025_REG_VALRTMIN1, &vmin_th, 1);
 
        RTINFO("vmax_th=0x%02x, vmin_th=0x%02x\n", vmax_th, vmin_th);
        return 0;
 }
 
-static int rt5025_battery_suspend(struct platform_device *pdev, pm_message_t state)
+static int rt5025_gauge_reginit(struct i2c_client *client)
+{
+       rt5025_reg_block_write(client, RT5025_REG_VALRTMAX,
+               5, gauge_init_regval);
+       rt5025_reg_write(client, RT5025_REG_IRQCTL, 0x00);
+       rt5025_reg_read(client, RT5025_REG_IRQFLG);
+       RTINFO("\n");
+       return 0;
+}
+
+static int rt5025_battery_suspend(struct platform_device *pdev,
+       pm_message_t state)
 {
        struct rt5025_battery_info *bi = platform_get_drvdata(pdev);
+
        RTINFO("\n");
-       //rt5025_get_timer(bi);
-       //bi->last_event = ktime_get();
+       /*rt5025_get_timer(bi);*/
+       /*bi->last_event = ktime_get();*/
        bi->last_event = current_kernel_time();
 
-       //cy add for battery parameter backup
+       /*cy add for battery parameter backup
        //rt5025_battery_parameter_backup(bi);
 
        //rt5025_channel_cc(bi, false);
-       //rt5025_update(bi);
+       //rt5025_update(bi);*/
        bi->device_suspend = true;
        cancel_delayed_work_sync(&bi->monitor_work);
        /* prevent suspend before starting the alarm */
-       //bi->update_time = SUSPEND_POLL;
-       rt5025_alert_setting(bi,MAXVOLT, false);
-       rt5025_alert_setting(bi,MINVOLT1,false);
+       /*bi->update_time = SUSPEND_POLL;*/
+       rt5025_alert_setting(bi, MAXVOLT, false);
+       rt5025_alert_setting(bi, MINVOLT1, false);
        rt5025_battery_sleepvth_setting(bi);
-       rt5025_alert_setting(bi,MAXVOLT, true);
-       rt5025_alert_setting(bi,MINVOLT1,true);
-       RTINFO("RM=%d\n",bi->rm);
+       if (bi->status == POWER_SUPPLY_STATUS_CHARGING)
+               rt5025_alert_setting(bi, MAXVOLT, true);
+       else if (bi->status == POWER_SUPPLY_STATUS_DISCHARGING)
+               rt5025_alert_setting(bi, MINVOLT1, true);
+       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;
+
+       /*ktime_t now;
        //struct timespec now = current_kernel_time();
        //struct timeval tv;
        //long time_interval;
@@ -1723,9 +1722,9 @@ static int rt5025_battery_resume(struct platform_device *pdev)
 
        //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);  
+       //RTINFO("Sleep time=%d, RM=%d",(int)time_interval,bi->rm);
 
-       //rt5025_channel_cc(bi, true);
+       //rt5025_channel_cc(bi, true);*/
        bi->last_suspend = true;
        bi->device_suspend = false;
        schedule_delayed_work(&bi->monitor_work, 0);
@@ -1751,33 +1750,38 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        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 = devm_kzalloc(&pdev->dev, sizeof(*bi), GFP_KERNEL);
+       if (!bi)
+               return -ENOMEM;
 
-       bi->last_poll = alarm_get_elapsed_realtime();
-       alarm_init(&bi->wakeup_alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
-               rt5025_gauge_alarm);
+       bi->client = chip->i2c;
 
        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");
-       wake_lock_init(&bi->status_wake_lock, WAKE_LOCK_SUSPEND, "battery-status-changed");
+
+       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");
+       wake_lock_init(&bi->status_wake_lock,
+               WAKE_LOCK_SUSPEND, "battery-status-changed");
+       wake_lock_init(&bi->smooth100_wake_lock,
+               WAKE_LOCK_SUSPEND, "smooth100_soc_wake_lock");
+       wake_lock_init(&bi->smooth0_wake_lock,
+               WAKE_LOCK_SUSPEND, "smooth0_soc_wake_lock");
+       wake_lock_init(&bi->full_battery_wake_lock,
+               WAKE_LOCK_SUSPEND, "full_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);
+       mutex_init(&bi->status_change_lock);
+       /* Write trimed data */
+       /*rt5025_pretrim(client);*/
+       rt5025_gauge_reginit(bi->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;
@@ -1786,84 +1790,96 @@ static int rt5025_battery_probe(struct platform_device *pdev)
        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.name = RT_BATT_NAME;
        bi->battery.type = POWER_SUPPLY_TYPE_BATTERY;
+       bi->battery.set_property = rt5025_set_property;
        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");
+               pr_err("[RT5025] power supply register failed\n");
                goto err_wake_lock;
        }
-  
 
-       //wake_lock(&bi->monitor_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));
+       schedule_delayed_work(&bi->monitor_work, INIT_POLL*HZ);
        chip->battery_info = bi;
 
        pr_info("rt5025-battery driver is successfully loaded\n");
-       
-  return 0;
 
+       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");
-       if (bi->soc == 0 && bi->cal_fcc != 0 )
-       {
-               bi->fcc_aging = bi->cal_fcc/3600 - (bi->fcc -bi->fcc_aging);
+       if (bi->soc == 0 && bi->cal_fcc != 0) {
+               /*d. FCC update limitation +/-3%; 2013/12/27
+               //bi->fcc_aging = bi->cal_fcc/3600 - (bi->fcc -bi->fcc_aging);*/
+               u16 fcc_new  = 0;
+
+               fcc_new = bi->cal_fcc / 3600 - (bi->fcc - bi->fcc_aging);
+               if (fcc_new > ((bi->fcc_aging * 103) / 100))
+                       bi->fcc_aging = (bi->fcc_aging * 103) / 100;
+               else if (fcc_new < ((bi->fcc_aging * 97) / 100))
+                       bi->fcc_aging = (bi->fcc_aging * 97) / 100;
+               else
+                       bi->fcc_aging = fcc_new;
+
                RTINFO("bi->cal_fcc=%d\n", bi->cal_fcc);
        }
        rt5025_battery_parameter_backup(bi);
        RTINFO("\n");
 }
 
-static struct platform_driver rt5025_battery_driver = 
-{
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-battery",},
+       {},
+};
+
+static struct platform_driver rt5025_battery_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-battery",
+               .name = RT5025_DEV_NAME "-battery",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_battery_probe,
-       .remove = __devexit_p(rt5025_battery_remove),
+       .remove = rt5025_battery_remove,
        .shutdown = rt5025_battery_shutdown,
        .suspend = rt5025_battery_suspend,
        .resume = rt5025_battery_resume,
 };
 
-static int __init rt5025_battery_init(void)
+static int rt5025_battery_init(void)
 {
        return platform_driver_register(&rt5025_battery_driver);
 }
-module_init(rt5025_battery_init);
+fs_initcall_sync(rt5025_battery_init);
 
-static void __exit rt5025_battery_exit(void)
+static void 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_LICENSE("GPL");
+MODULE_AUTHOR("Nick Hung <nick_hung@richtek.com>");
 MODULE_DESCRIPTION("battery gauge driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-battery");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-battery");
 MODULE_VERSION(RT5025_DRV_VER);
diff --git a/drivers/power/rt5025-charger.c b/drivers/power/rt5025-charger.c
new file mode 100755 (executable)
index 0000000..d7aee67
--- /dev/null
@@ -0,0 +1,1224 @@
+/*
+ *  drivers/power/rt5025-charger.c
+ *  Driver for Richtek RT5025 PMIC Charger driver
+ *
+ *  Copyright (C) 2014 Richtek Technology Corp.
+ *  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; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/of.h>
+#include <linux/power_supply.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */
+
+#include <linux/mfd/rt5025.h>
+#include <linux/power/rt5025-charger.h>
+#ifdef CONFIG_RT_POWER
+#include <linux/power/rt-power.h>
+#endif /* #ifdef CONFIG_RT_POWER */
+
+static unsigned char chg_init_regval[] = {
+       0x12, /*REG 0x02*/
+       0x8C, /*REG 0x03*/
+       0x03, /*REG 0x04*/
+       0x20, /*REG 0x05*/
+       0x14, /*REG 0x06*/
+       0x40, /*REG 0x07*/
+       0xDA, /*REG 0x30*/
+       0xDA, /*REG 0x32*/
+       0x43, /*REG 0x34*/
+};
+
+static char *rtdef_chg_name = "rt-charger";
+
+static char *rt_charger_supply_list[] = {
+       "none",
+};
+
+static enum power_supply_property rt_charger_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TEMP,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_MAX,
+       POWER_SUPPLY_PROP_CURRENT_AVG,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+};
+
+static void rt_charger_set_batt_status(struct rt5025_charger_info *ci);
+
+static int rt_charger_get_property(struct power_supply *psy, enum power_supply_property psp, \
+                       union power_supply_propval *val)
+{
+       struct rt5025_charger_info *ci = dev_get_drvdata(psy->dev->parent);
+       int ret = 0;
+       int regval = 0;
+       #ifdef CONFIG_BATTERY_RT5025
+       struct power_supply *bat_psy = power_supply_get_by_name(RT_BATT_NAME);
+       union power_supply_propval pval;
+       #endif
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               val->intval = ci->online;
+               break;
+       case POWER_SUPPLY_PROP_STATUS:
+               val->intval = ci->chg_status;
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL7);
+               if (regval < 0) {
+                       ret = -EINVAL;
+               } else {
+                       if (regval & RT5025_CHGCEN_MASK)
+                               val->intval = 1;
+                       else
+                               val->intval = 0;
+               }
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+               val->intval = 0;
+               #ifdef CONFIG_BATTERY_RT5025
+                       if (bat_psy) {
+                               ret = bat_psy->get_property(bat_psy, POWER_SUPPLY_PROP_TEMP_AMBIENT,\
+                                       &pval);
+                               if (ret < 0)
+                                       dev_err(ci->dev, "get ic temp fail\n");
+                               else
+                                       val->intval = pval.intval;
+                       }
+               #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               val->intval = ci->charger_cable;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+               val->intval = 2000;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL4);
+               if (regval < 0) {
+                       ret = -EINVAL;
+               } else {
+                       regval &= RT5025_CHGAICR_MASK;
+                       regval >>= RT5025_CHGAICR_SHFT;
+                       switch (regval) {
+                       case 0:
+                               val->intval = 100;
+                               break;
+                       case 1:
+                               val->intval = 500;
+                               break;
+                       case 2:
+                               val->intval = 1000;
+                               break;
+                       case 3:
+                               val->intval = 0;
+                               break;
+                       default:
+                               ret = -EINVAL;
+                               break;
+                       }
+               }
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL4);
+               if (regval < 0) {
+                       ret = -EINVAL;
+               } else {
+                       regval &= RT5025_CHGICC_MASK;
+                       regval >>= RT5025_CHGICC_SHFT;
+                       val->intval = 500 + regval * 100;
+                       }
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               regval = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL3);
+               if (regval < 0) {
+                               ret = -EINVAL;
+               } else {
+                               regval &= RT5025_CHGCV_MASK;
+                               regval >>= RT5025_CHGCV_SHFT;
+                               val->intval = regval * 20 + 3500;
+               }
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               val->intval = 3500;
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               val->intval = 4440;
+               break;
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+static int rt_charger_set_property(struct power_supply *psy, enum power_supply_property psp, \
+                               const union power_supply_propval *val)
+{
+       struct rt5025_charger_info *ci = dev_get_drvdata(psy->dev->parent);
+       int ret = 0;
+       int regval = 0;
+       RTINFO("prop = %d, val->intval = %d\n", psp, val->intval);
+       switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               ci->online = val->intval;
+               if (ci->online) {
+                       if (ci->te_en) {
+                               ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGTEEN_MASK);
+                               /*charger workaround*/
+                               mdelay(150);
+                               /*turn  on recharge irq enable*/
+                               chg_init_regval[8] |= RT5025_CHRCHGI_MASK;
+                               rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN3, chg_init_regval[8]);
+                               /*turn on chterm irq enable*/
+                               chg_init_regval[7] |= RT5025_CHTERMI_MASK;
+                               rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN2, chg_init_regval[7]);
+                       }
+                       ci->chg_status = POWER_SUPPLY_STATUS_CHARGING;
+                       rt_charger_set_batt_status(ci);
+               } else {
+                       if (ci->te_en) {
+                               ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGTEEN_MASK);
+                               /*charger workaround*/
+                               /*turn off chterm irq enable*/
+                               chg_init_regval[7] &= ~RT5025_CHTERMI_MASK;
+                               rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN2, chg_init_regval[7]);
+                               /*turn  off recharge irq enable*/
+                               chg_init_regval[8] &= ~RT5025_CHRCHGI_MASK;
+                               rt5025_reg_write(ci->i2c, RT5025_REG_IRQEN3, chg_init_regval[8]);
+                       }
+                       ci->chg_status = POWER_SUPPLY_STATUS_DISCHARGING;
+                       rt_charger_set_batt_status(ci);
+               }
+               break;
+       case POWER_SUPPLY_PROP_PRESENT:
+               if (ci->online && val->intval) {
+                       int icc;
+                       int battemp_icc;
+                       int inttemp_icc;
+                       union power_supply_propval pval;
+
+                       if (ci->charger_cable == POWER_SUPPLY_TYPE_MAINS)
+                               battemp_icc = inttemp_icc = (ci->screen_on ?\
+                                       ci->screenon_icc:ci->acchg_icc);
+                       else if (ci->charger_cable == POWER_SUPPLY_TYPE_USB_DCP)
+                               battemp_icc = inttemp_icc = (ci->screen_on ?\
+                                       ci->screenon_icc:ci->usbtachg_icc);
+                       else
+                               battemp_icc = inttemp_icc = (ci->screen_on ?\
+                                       ci->screenon_icc:ci->usbchg_icc);
+                       if (ci->battemp_region == RT5025_BATTEMP_COLD ||\
+                               ci->battemp_region == RT5025_BATTEMP_HOT)
+                               battemp_icc = 10;
+                       else if (ci->battemp_region == RT5025_BATTEMP_COOL ||\
+                               ci->battemp_region == RT5025_BATTEMP_WARM)
+                               battemp_icc /= 2;
+
+                       if (ci->inttemp_region == RT5025_INTTEMP_WARM)
+                               inttemp_icc -= 300;
+                       else if (ci->inttemp_region == RT5025_INTTEMP_HOT)
+                               inttemp_icc -= 800;
+
+                       if (inttemp_icc < 0)
+                               inttemp_icc = 10;
+
+                       icc = min(battemp_icc, inttemp_icc);
+                       pval.intval = icc;
+                       ret = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &pval);
+                       if (ret < 0)
+                               dev_err(ci->dev, "set final icc fail\n");
+               }
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               ci->charger_cable = val->intval;
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_AVG:
+               if (0 < val->intval && val->intval <= 100)
+                       regval = 0;
+               else if (val->intval <= 500)
+                       regval = 1;
+               else if (val->intval <= 1000)
+                       regval = 2;
+               else
+                       regval = 3;
+               if (!ci->batabs)
+                       ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL4, \
+                               RT5025_CHGAICR_MASK, regval << RT5025_CHGAICR_SHFT);
+               break;
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               if (val->intval < 0) {
+                       ci->otg_en = 1;
+                       regval = -1;
+                       #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN
+                       ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_VBUSHZ_MASK);
+                       if (ret < 0)
+                               dev_err(ci->dev, "set vbus hz fail\n");
+                       #else
+                       ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBCEN_MASK);
+                       if (ret < 0)
+                               dev_err(ci->dev, "shutdown chg buck fail\n");
+                       #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
+               } else if (val->intval == 0) {
+                       ci->otg_en = 0;
+                       regval = -1;
+                       #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN
+                       ret = rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_VBUSHZ_MASK);
+                       if (ret < 0)
+                               dev_err(ci->dev, "clear vbus hz fail\n");
+                       #else
+                       ret = rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL2, RT5025_CHGBCEN_MASK);
+                       if (ret < 0)
+                               dev_err(ci->dev, "turnon chg buck fail\n");
+                       #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
+               } else if (val->intval > 0 && val->intval < 500) {
+                               regval = 0;
+               } else if (val->intval > 2000) {
+                               regval = 15;
+               } else {
+                               regval = (val->intval - 500) / 100;
+               }
+
+               if (regval >= 0)
+                       ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, \
+                                       regval<<RT5025_CHGICC_SHFT);
+
+               if (val->intval > 0 && val->intval < 500)
+                       rt5025_clr_bits(ci->i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK);
+               else
+                       rt5025_set_bits(ci->i2c, RT5025_REG_CHGCTL7, RT5025_CHGCEN_MASK);
+               break;
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               if (val->intval < 3500)
+                       regval = 0;
+               else if (val->intval > 4440)
+                       regval = 0x3A;
+               else
+                       regval = (val->intval - 3500) / 20;
+               ret = rt5025_assign_bits(ci->i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, \
+                                       regval << RT5025_CHGCV_SHFT);
+               break;
+       case POWER_SUPPLY_PROP_TEMP:
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+       case POWER_SUPPLY_PROP_CURRENT_MAX:
+       case POWER_SUPPLY_PROP_STATUS:
+       default:
+               ret = -EINVAL;
+       }
+       return ret;
+}
+
+#ifdef CONFIG_BATTERY_RT5025
+static int rt5025_set_tempalrt(struct rt5025_charger_info *ci)
+{
+       int rc = 0;
+
+       rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+               RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0x00);
+       if (ci->battemp_region == RT5025_BATTEMP_HOT) {
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[6]);
+               rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+                       RT5025_TALRTMX_MASK, 0xFF);
+       } else if (ci->battemp_region == RT5025_BATTEMP_WARM) {
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[4]);
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[7]);
+               rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+                       RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF);
+       } else if (ci->battemp_region == RT5025_BATTEMP_NORMAL) {
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[2]);
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[5]);
+               rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+                       RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF);
+       } else if (ci->battemp_region == RT5025_BATTEMP_COOL) {
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMAX, ci->temp_scalar[0]);
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[3]);
+               rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+                       RT5025_TALRTMX_MASK|RT5025_TALRTMN_MASK, 0xFF);
+       } else {
+               rt5025_reg_write(ci->i2c, RT5025_REG_TALRTMIN, ci->temp_scalar[1]);
+               rt5025_assign_bits(ci->i2c, RT5025_REG_IRQCTL,\
+                       RT5025_TALRTMN_MASK, 0xFF);
+       }
+       return rc;
+}
+#endif /* #ifdef CONFIG_BATTERY_RT5025 */
+
+static void rt_charger_set_batt_status(struct rt5025_charger_info *ci)
+{
+       #ifdef CONFIG_BATTERY_RT5025
+       struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME);
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (!psy) {
+               dev_err(ci->dev, "can't get battery supply\n");
+               return;
+       }
+       pval.intval = ci->chg_status;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_STATUS, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set battery status fail\n");
+       power_supply_changed(psy);
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+}
+
+static int rt_charger_check_battery_present(struct rt5025_charger_info *ci)
+{
+       int rc = 1;
+       #ifdef CONFIG_BATTERY_RT5025
+       struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME);
+       union power_supply_propval pval;
+
+       if (!psy) {
+               dev_err(ci->dev, "can't get battery supply\n");
+               return rc;
+       }
+       rc = psy->get_property(psy, POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
+       if (rc < 0) {
+               dev_err(ci->dev, "get battery voltage fail\n");
+       } else {
+               if (pval.intval < (ci->chg_volt - 200) * 1000)
+                       rc = 0;
+               else
+                       rc = 1;
+       }
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+       return rc;
+}
+
+static void rt5025_batabs_irq_handler(void *info, int eventno)
+{
+       struct rt5025_charger_info *ci = info;
+       struct power_supply *psy = &ci->psy;
+       union power_supply_propval pval;
+       int rc = 0;
+
+       #ifdef CONFIG_BATTERY_RT5025
+               struct power_supply *bat_psy = power_supply_get_by_name(RT_BATT_NAME);
+
+               pval.intval = 0;
+               if (!bat_psy) {
+                       dev_err(ci->dev, "get rt-battery supply fail\n");
+               } else {
+                       rc = bat_psy->set_property(bat_psy,
+                               POWER_SUPPLY_PROP_PRESENT, &pval);
+                       if (rc < 0)
+                               dev_err(ci->dev, "set battery not present fail\n");
+                       power_supply_changed(bat_psy);
+               }
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+       /*set aicr to disable*/
+       pval.intval = 2000;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_AVG, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set aicr to disable fail\n");
+       /*set icc to 2000*/
+       pval.intval = 2000;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_CURRENT_NOW, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set icc to 2000 fail\n");
+       /*set online = 0, due to bat absense*/
+       pval.intval = 0;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set charger offline fail\n");
+       ci->batabs = 1;
+       ci->te_en = 0;
+}
+
+static void rt5025_acin_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_RT_POWER
+       struct rt5025_charger_info *ci = info;
+       #ifndef CONFIG_RT_SUPPORT_ACUSB_DUALIN
+       struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME);
+       #else
+       struct power_supply *psy = power_supply_get_by_name(RT_AC_NAME);
+       #endif /* #ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (!psy) {
+               dev_err(ci->dev, "could not get psy supply\n");
+               return;
+       }
+       pval.intval = 1;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set ac online fail\n");
+       power_supply_changed(psy);
+       dev_info(ci->dev, "%s\n", __func__);
+       #endif /* #ifdef CONFIG_RT_POWER */
+}
+
+static void rt5025_acout_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_RT_POWER
+       struct rt5025_charger_info *ci = info;
+       #ifndef CONFIG_RT_SUPPORT_ACUSB_DUALIN
+       struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME);
+       #else
+       struct power_supply *psy = power_supply_get_by_name(RT_AC_NAME);
+       #endif /* ifdef CONFIG_RT_SUPPORT_ACUSB_DUALIN */
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (!psy) {
+               dev_err(ci->dev, "could not get rt-usb supply\n");
+               return;
+       }
+       pval.intval = 0;
+       rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+       if (rc < 0)
+               dev_err(ci->dev, "set ac offline fail\n");
+       power_supply_changed(psy);
+       dev_info(ci->dev, "%s\n", __func__);
+       #endif /* #ifdef CONFIG_RT_POWER */
+}
+
+static void rt5025_usbin_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_RT_POWER
+       struct rt5025_charger_info *ci = info;
+       struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME);
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (!psy) {
+               dev_err(ci->dev, "could not get rt-usb supply\n");
+               return;
+       }
+       if (!ci->otg_en) {
+               pval.intval = 1;
+               rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set ac online fail\n");
+               power_supply_changed(psy);
+       }
+       dev_info(ci->dev, "%s\n", __func__);
+       #endif /* #ifdef CONFIG_RT_POWER */
+}
+
+static void rt5025_usbout_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_RT_POWER
+       struct rt5025_charger_info *ci = info;
+       struct power_supply *psy = power_supply_get_by_name(RT_USB_NAME);
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (!psy) {
+               dev_err(ci->dev, "could not get rt-usb supply\n");
+               return;
+       }
+       if (!ci->otg_en) {
+               pval.intval = 0;
+               rc = psy->set_property(psy, POWER_SUPPLY_PROP_ONLINE, &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set ac offline fail\n");
+               power_supply_changed(psy);
+       }
+       dev_info(ci->dev, "%s\n", __func__);
+       #endif /* #ifdef CONFIG_RT_POWER */
+}
+
+static void rt5025_talrtmax_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_BATTERY_RT5025
+       struct rt5025_charger_info *ci = info;
+       union power_supply_propval pval;
+       int rc = 0;
+
+       switch (ci->battemp_region) {
+       case RT5025_BATTEMP_COLD:
+               dev_warn(ci->dev, "cold than cold???\n");
+               break;
+       case RT5025_BATTEMP_COOL:
+               dev_info(ci->dev, "cool-> cold\n");
+               ci->battemp_region = RT5025_BATTEMP_COLD;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_NORMAL:
+               dev_info(ci->dev, "normal-> cool\n");
+               ci->battemp_region = RT5025_BATTEMP_COOL;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_WARM:
+               dev_info(ci->dev, "warm-> normal\n");
+               ci->battemp_region = RT5025_BATTEMP_NORMAL;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_HOT:
+               dev_info(ci->dev, "hot-> warm\n");
+               ci->battemp_region = RT5025_BATTEMP_WARM;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       default:
+               break;
+       }
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+}
+
+static void rt5025_talrtmin_irq_handler(void *info, int eventno)
+{
+       #ifdef CONFIG_BATTERY_RT5025
+       struct rt5025_charger_info *ci = info;
+       union power_supply_propval pval;
+       int rc = 0;
+
+       switch (ci->battemp_region) {
+       case RT5025_BATTEMP_COLD:
+               dev_info(ci->dev, "cold-> cool\n");
+               ci->battemp_region = RT5025_BATTEMP_COOL;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_COOL:
+               dev_info(ci->dev, "cool-> normal\n");
+               ci->battemp_region = RT5025_BATTEMP_NORMAL;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_NORMAL:
+                       dev_info(ci->dev, "normal-> warm\n");
+                       ci->battemp_region = RT5025_BATTEMP_WARM;
+                       rt5025_set_tempalrt(ci);
+                       pval.intval = 1;
+                       rc = ci->psy.set_property(&ci->psy,
+                               POWER_SUPPLY_PROP_PRESENT,\
+                               &pval);
+                       if (rc < 0)
+                               dev_err(ci->dev, "set present fail\n");
+                       break;
+       case RT5025_BATTEMP_WARM:
+               dev_info(ci->dev, "warm-> hot\n");
+               ci->battemp_region = RT5025_BATTEMP_HOT;
+               rt5025_set_tempalrt(ci);
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT,\
+                       &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set present fail\n");
+               break;
+       case RT5025_BATTEMP_HOT:
+               dev_warn(ci->dev, "hot than hot???\n");
+               break;
+       default:
+               break;
+       }
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+}
+
+static void rt5025_general_irq_handler(void *info, int eventno)
+{
+       struct rt5025_charger_info *ci = info;
+
+       RTINFO("eventno=%02d\n", eventno);
+       switch (eventno) {
+       case CHGEVENT_CHRCHGI:
+               if (!ci->online) {
+                       dev_warn(ci->dev, "recharge false alarm\n");
+               } else {
+                       union power_supply_propval pval;
+
+                       dev_info(ci->dev, "recharge occur\n");
+                       ci->chg_status = POWER_SUPPLY_STATUS_CHARGING;
+                       pval.intval = ci->chg_volt;
+                       rt_charger_set_batt_status(ci);
+                       ci->psy.set_property(&ci->psy,
+                               POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
+               }
+               break;
+       case CHGEVENT_CHTERMI:
+               if (!ci->online) {
+                               dev_warn(ci->dev, "eoc false alarm\n");
+               } else {
+                       if (rt_charger_check_battery_present(ci)) {
+                               union power_supply_propval pval;
+
+                               if (ci->chg_status == POWER_SUPPLY_STATUS_FULL)
+                                       return;
+                               dev_info(ci->dev, "eoc really occur\n");
+                               ci->chg_status = POWER_SUPPLY_STATUS_FULL;
+                               rt_charger_set_batt_status(ci);
+                               pval.intval = ci->chg_volt-50;
+                               ci->psy.set_property(&ci->psy,
+                                       POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
+                       } else {
+                               dev_info(ci->dev, "no battery condition\n");
+                               rt5025_batabs_irq_handler(ci, eventno);
+                       }
+               }
+               break;
+       case CHGEVENT_TALRTMAX:
+               #ifdef CONFIG_BATTERY_RT5025
+               rt5025_set_tempalrt(ci);
+               #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+               break;
+       case CHGEVENT_TALRTMIN:
+               #ifdef CONFIG_BATTERY_RT5025
+               rt5025_set_tempalrt(ci);
+               #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+               break;
+       default:
+               break;
+       }
+}
+
+static rt_irq_handler rt_chgirq_handler[CHGEVENT_MAX] = {
+       [CHGEVENT_TIMEOUT_CC] = rt5025_general_irq_handler,
+       [CHGEVENT_TIMEOUT_PC] = rt5025_general_irq_handler,
+       [CHGEVENT_CHVSREGI] = rt5025_general_irq_handler,
+       [CHGEVENT_CHTREGI] = rt5025_general_irq_handler,
+       [CHGEVENT_CHRCHGI] = rt5025_general_irq_handler,
+       [CHGEVENT_CHTERMI] = rt5025_general_irq_handler,
+       [CHGEVENT_CHBATOVI] = rt5025_general_irq_handler,
+       [CHGEVENT_CHGOODI_INUSB] = rt5025_general_irq_handler,
+       [CHGEVENT_CHBADI_INUSB] = rt5025_general_irq_handler,
+       [CHGEVENT_CHSLPI_INUSB] = rt5025_usbout_irq_handler,
+       [CHGEVENT_CHGOODI_INAC] = rt5025_general_irq_handler,
+       [CHGEVENT_CHBADI_INAC] = rt5025_general_irq_handler,
+       [CHGEVENT_CHSLPI_INAC] = rt5025_acout_irq_handler,
+       [CHGEVENT_BATABS] = rt5025_batabs_irq_handler,
+       [CHGEVENT_INUSB_PLUGIN] = rt5025_usbin_irq_handler,
+       [CHGEVENT_INUSBOVP] = rt5025_general_irq_handler,
+       [CHGEVENT_INAC_PLUGIN] = rt5025_acin_irq_handler,
+       [CHGEVENT_INACOVP] = rt5025_general_irq_handler,
+       [CHGEVENT_TALRTMIN] = rt5025_talrtmin_irq_handler,
+       [CHGEVENT_TALRTMAX] = rt5025_talrtmax_irq_handler,
+};
+
+void rt5025_charger_irq_handler(struct rt5025_charger_info *ci, unsigned int irqevent)
+{
+       int i;
+       #ifdef CONFIG_BATTERY_RT5025
+       unsigned int enable_irq_event = (RT5025_TALRTMX_MASK | RT5025_TALRTMN_MASK)<<24 | \
+                       (chg_init_regval[6] << 16) | (chg_init_regval[7] << 8) |  chg_init_regval[8];
+       #else
+       unsigned int enable_irq_event = (chg_init_regval[6] << 16)
+               | (chg_init_regval[7] << 8)| \
+                               chg_init_regval[8];
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+       unsigned int final_irq_event = irqevent&enable_irq_event;
+
+       /*charger workaround (TE+RECHARGE)*/
+       if (final_irq_event & (1 << CHGEVENT_CHTERMI) && \
+               final_irq_event & (1 << CHGEVENT_CHRCHGI))
+               final_irq_event &= ~((1 << CHGEVENT_CHTERMI) | (1 << CHGEVENT_CHRCHGI));
+       i = rt5025_reg_read(ci->i2c, RT5025_REG_CHGCTL1);
+       if (i < 0) {
+               dev_err(ci->dev, "read CHGCTL1 fail\n");
+               i = 0;
+       }
+       /*acin+acout*/
+       if (final_irq_event & (1 << CHGEVENT_INAC_PLUGIN) && \
+               final_irq_event & (1 << CHGEVENT_CHSLPI_INAC)) {
+               if (i & RT5025_ACUSABLE_MASK)
+                       final_irq_event &= ~(1<<CHGEVENT_CHSLPI_INAC);
+               else
+                       final_irq_event &= ~(1<<CHGEVENT_INAC_PLUGIN);
+       }
+       /*usbin+usbout*/
+       if (final_irq_event & (1 << CHGEVENT_INUSB_PLUGIN) && \
+               final_irq_event & (1 << CHGEVENT_CHSLPI_INUSB)) {
+               if (i & RT5025_USBUSABLE_MASK)
+                       final_irq_event &= ~(1 << CHGEVENT_CHSLPI_INUSB);
+               else
+                       final_irq_event &= ~(1 << CHGEVENT_INUSB_PLUGIN);
+       }
+       for (i = 0; i < CHGEVENT_MAX; i++) {
+               if ((final_irq_event & (1 << i)) && rt_chgirq_handler[i])
+                       rt_chgirq_handler[i](ci, i);
+       }
+}
+EXPORT_SYMBOL(rt5025_charger_irq_handler);
+
+static void rt5025_tempmon_work(struct work_struct *work)
+{
+       struct rt5025_charger_info *ci = container_of(work, \
+               struct rt5025_charger_info, tempmon_work.work);
+       #ifdef CONFIG_BATTERY_RT5025
+       struct power_supply *psy = power_supply_get_by_name(RT_BATT_NAME);
+       union power_supply_propval pval;
+       int inttemp_region;
+       #endif
+
+       RTINFO("\n");
+       #ifdef CONFIG_BATTERY_RT5025
+               if (!psy) {
+                       dev_err(ci->dev, "could not get rt-battery psy\n");
+                       return;
+               }
+               if (!ci->init_once) {
+                       /*battemp init*/
+                       int i = 0;
+
+                       pval.intval = 23; /* magic code*/
+                       psy->get_property(psy, POWER_SUPPLY_PROP_TEMP, &pval);
+                       for (i = 3; i >= 0; i--)
+                               if (pval.intval > ci->temp[i])
+                                       break;
+                       if (i == 3)
+                               ci->battemp_region = RT5025_BATTEMP_HOT;
+                       else if (i == 2)
+                               ci->battemp_region = RT5025_BATTEMP_WARM;
+                       else if (i == 1)
+                               ci->battemp_region = RT5025_BATTEMP_NORMAL;
+                       else if (i == 0)
+                               ci->battemp_region = RT5025_BATTEMP_COOL;
+                       else
+                               ci->battemp_region = RT5025_BATTEMP_COLD;
+                       rt5025_set_tempalrt(ci);
+                       ci->init_once = 1;
+               }
+
+               psy->get_property(psy, POWER_SUPPLY_PROP_TEMP_AMBIENT, &pval);
+               if (pval.intval > 1000)
+                       inttemp_region = RT5025_INTTEMP_HOT;
+               else if (pval.intval > 750)
+                       inttemp_region = RT5025_INTTEMP_WARM;
+               else
+                       inttemp_region = RT5025_INTTEMP_NORMAL;
+
+               if (inttemp_region != ci->inttemp_region) {
+                       ci->inttemp_region = inttemp_region;
+                       pval.intval = 1;
+                       rt_charger_set_property(&ci->psy,
+                               POWER_SUPPLY_PROP_PRESENT, &pval);
+               }
+       #endif /* #ifdef CONFIG_BATTERY_RT5025 */
+       if (!ci->suspend)
+               schedule_delayed_work(&ci->tempmon_work, 5*HZ);
+}
+
+static int rt5025_charger_reginit(struct i2c_client *client)
+{
+       rt5025_reg_block_write(client, RT5025_REG_CHGCTL2, 6, chg_init_regval);
+       /*set all to be masked*/
+       rt5025_reg_write(client, RT5025_REG_IRQEN1, 0x00);
+       rt5025_reg_write(client, RT5025_REG_IRQEN2, 0x00);
+       rt5025_reg_write(client, RT5025_REG_IRQEN3, 0x00);
+       /*just clear the old irq event*/
+       rt5025_reg_read(client, RT5025_REG_IRQSTAT1);
+       rt5025_reg_read(client, RT5025_REG_IRQSTAT2);
+       rt5025_reg_read(client, RT5025_REG_IRQSTAT3);
+       /*set enable irqs as we want*/
+       rt5025_reg_write(client, RT5025_REG_IRQEN1, chg_init_regval[6]);
+       rt5025_reg_write(client, RT5025_REG_IRQEN2, chg_init_regval[7]);
+       rt5025_reg_write(client, RT5025_REG_IRQEN3, chg_init_regval[8]);
+       RTINFO("\n");
+       return 0;
+}
+
+static int rt_parse_dt(struct rt5025_charger_info *ci, struct device *dev)
+{
+       #ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+       u32 val;
+
+       if (of_property_read_bool(np, "rt,te_en"))
+               ci->te_en = 1;
+
+       if (of_property_read_u32(np, "rt,iprec", &val)) {
+               dev_info(dev, "no iprec property, use default value\n");
+       } else{
+               if (val > RT5025_IPREC_MAX)
+                       val = RT5025_IPREC_MAX;
+               chg_init_regval[4] &= (~RT5025_CHGIPREC_MASK);
+               chg_init_regval[4] |= (val << RT5025_CHGIPREC_SHFT);
+       }
+
+       if (of_property_read_u32(np, "rt,ieoc", &val)) {
+               dev_info(dev, "no ieoc property, use the default value\n");
+       } else {
+               if (val  > RT5025_IEOC_MAX)
+                       val = RT5025_IEOC_MAX;
+               chg_init_regval[4] &= (~RT5025_CHGIEOC_MASK);
+               chg_init_regval[4] |= (val << RT5025_CHGIEOC_SHFT);
+       }
+
+       if (of_property_read_u32(np, "rt,vprec", &val)) {
+               dev_info(dev, "no vprec property, use the default value\n");
+       } else {
+               if (val > RT5025_VPREC_MAX)
+                       val = RT5025_VPREC_MAX;
+               chg_init_regval[4] &= (~RT5025_CHGVPREC_MASK);
+               chg_init_regval[4] |= (val << RT5025_CHGVPREC_SHFT);
+       }
+
+       if (of_property_read_u32(np, "rt,vdpm", &val)) {
+               dev_info(dev, "no vdpm property, use the default value\n");
+       } else {
+               if (val > RT5025_VDPM_MAX)
+                       val = RT5025_VDPM_MAX;
+               chg_init_regval[3] &= (~RT5025_CHGVDPM_MASK);
+               chg_init_regval[3] |= (val << RT5025_CHGVDPM_SHFT);
+       }
+
+       if (of_property_read_u32(np, "rt,chg_volt", &val)) {
+               dev_info(dev, "no chg_volt property, use 4200 as the default value\n");
+               ci->chg_volt = 4200;
+       } else {
+               ci->chg_volt = val;
+       }
+
+       if (of_property_read_u32(np, "rt,acchg_icc", &val)) {
+               dev_info(dev, "no acchg_icc property, use 2000 as the default value\n");
+               ci->acchg_icc = 2000;
+       } else {
+               ci->acchg_icc = val;
+       }
+
+       if (of_property_read_u32(np, "rt,usbtachg_icc", &val)) {
+               dev_info(dev, "no usbtachg_icc property, use 2000 as the default value\n");
+               ci->usbtachg_icc = 2000;
+       } else {
+               ci->usbtachg_icc = val;
+       }
+
+       if (of_property_read_u32(np, "rt,usbchg_icc", &val)) {
+               dev_info(dev, "no usbchg_icc property, use 500 as the default value\n");
+               ci->usbchg_icc = 500;
+       } else {
+               ci->usbchg_icc = val;
+       }
+
+       if (of_property_read_u32(np, "rt,screenon_icc", &val)) {
+               dev_info(dev, "no screenon_icc property, use 500 as the default value\n");
+               ci->screenon_icc = 500;
+       } else {
+               ci->screenon_icc = val;
+       }
+
+       if (of_property_read_bool(np, "rt,screenon_adjust")) {
+               ci->screenon_adjust = 1;
+               ci->screen_on = 1;
+       }
+
+       if (of_property_read_u32_array(np, "rt,temp",
+               ci->temp, 4)) {
+               dev_info(dev, "no temperature property, use default value\n");
+               ci->temp[0] = 0;
+               ci->temp[1] = 150;
+               ci->temp[2] = 500;
+               ci->temp[3] = 600;
+       }
+
+       if (of_property_read_u32_array(np, "rt,temp_scalar",
+               ci->temp_scalar, 8)) {
+               dev_info(dev, "no temp_scalar property, use default value\n");
+               ci->temp_scalar[0] = 0x30;
+               ci->temp_scalar[1] = 0x2B;
+               ci->temp_scalar[2] = 0x28;
+               ci->temp_scalar[3] = 0x22;
+               ci->temp_scalar[4] = 0x15;
+               ci->temp_scalar[5] = 0x10;
+               ci->temp_scalar[6] = 0x10;
+               ci->temp_scalar[7] = 0x0D;
+       }
+       #endif /* #ifdef CONFIG_OF */
+       rt5025_charger_reginit(ci->i2c);
+       RTINFO("\n");
+       return 0;
+}
+
+static int rt_parse_pdata(struct rt5025_charger_info *ci, struct device *dev)
+{
+       struct rt5025_charger_data *pdata = dev->platform_data;
+       int i = 0;
+
+       if (pdata->te_en)
+               ci->te_en = 1;
+
+       chg_init_regval[4] &= (~RT5025_CHGIPREC_MASK);
+       chg_init_regval[4] |= (pdata->iprec << RT5025_CHGIPREC_SHFT);
+
+       chg_init_regval[4] &= (~RT5025_CHGIEOC_MASK);
+       chg_init_regval[4] |= (pdata->ieoc << RT5025_CHGIEOC_SHFT);
+
+       chg_init_regval[4] &= (~RT5025_CHGVPREC_MASK);
+       chg_init_regval[4] |= (pdata->vprec << RT5025_CHGVPREC_SHFT);
+
+       chg_init_regval[3] &= (~RT5025_CHGVDPM_MASK);
+       chg_init_regval[3] |= (pdata->vdpm << RT5025_CHGVDPM_SHFT);
+
+       ci->chg_volt = pdata->chg_volt;
+       ci->acchg_icc = pdata->acchg_icc;
+       ci->usbtachg_icc = pdata->usbtachg_icc;
+       ci->usbchg_icc = pdata->usbchg_icc;
+       ci->screenon_icc = pdata->screenon_icc;
+       if (pdata->screenon_adjust) {
+               ci->screenon_adjust = 1;
+               /*default probe screen will on*/
+               ci->screen_on = 1;
+       }
+       for (i = 0; i < 4; i++)
+               ci->temp[i] = pdata->temp[i];
+       for (i = 0; i < 8; i++)
+               ci->temp_scalar[i] = pdata->temp_scalar[i];
+       rt5025_charger_reginit(ci->i2c);
+       RTINFO("\n");
+       return 0;
+}
+
+#ifdef CONFIG_RT_POWER
+static struct platform_device rt_power_dev = {
+       .name = "rt-power",
+       .id = -1,
+};
+#endif /* #ifdef CONFIG_RT_POWER */
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+static void rt5025_charger_earlysuspend(struct early_suspend *handler)
+{
+       struct rt5025_charger_info *ci = container_of(handler, \
+               struct rt5025_charger_info, early_suspend);
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (ci->screenon_adjust) {
+               ci->screen_on = 0;
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy,
+                       POWER_SUPPLY_PROP_PRESENT, &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set charger present property fail\n");
+       }
+}
+
+static void rt5025_charger_earlyresume(struct early_suspend *handler)
+{
+       struct rt5025_charger_info *ci = container_of(handler, \
+               struct rt5025_charger_info, early_suspend);
+       union power_supply_propval pval;
+       int rc = 0;
+
+       if (ci->screenon_adjust) {
+               ci->screen_on = 1;
+               pval.intval = 1;
+               rc = ci->psy.set_property(&ci->psy,
+                       POWER_SUPPLY_PROP_PRESENT, &pval);
+               if (rc < 0)
+                       dev_err(ci->dev, "set charger present property fail\n");
+       }
+}
+#endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */
+
+static int rt5025_charger_probe(struct platform_device *pdev)
+{
+       struct rt5025_chip *chip = dev_get_drvdata(pdev->dev.parent);
+       struct rt5025_platform_data *pdata =
+               (pdev->dev.parent)->platform_data;
+       #ifdef CONFIG_RT_POWER
+       struct rt_power_data *rt_power_pdata;
+       #endif /* #ifdef CONFIG_RT_POWER */
+       struct rt5025_charger_info *ci;
+       bool use_dt = pdev->dev.of_node;
+       int ret = 0;
+
+       ci = devm_kzalloc(chip->dev, sizeof(struct rt5025_charger_info), GFP_KERNEL);
+       if (!ci)
+               return -ENOMEM;
+
+       ci->i2c = chip->i2c;
+       ci->dev = &pdev->dev;
+       ci->chg_status = POWER_SUPPLY_STATUS_DISCHARGING;
+       ci->battemp_region = RT5025_BATTEMP_NORMAL;
+       ci->inttemp_region = RT5025_INTTEMP_NORMAL;
+       #ifdef CONFIG_RT_JEITA_REMOVE
+       ci->init_once = 1;
+       #endif /* #ifdef RT_JEITA_REMOVE */
+
+       if (use_dt) {
+               rt_parse_dt(ci, &pdev->dev);
+       } else {
+               if (!pdata) {
+                       ret = -EINVAL;
+                       goto out_dev;
+               }
+               pdev->dev.platform_data = pdata->chg_pdata;
+               rt_parse_pdata(ci, &pdev->dev);
+       }
+       INIT_DELAYED_WORK(&ci->tempmon_work, rt5025_tempmon_work);
+
+       platform_set_drvdata(pdev, ci);
+       /*power supply register*/
+       ci->psy.name = rtdef_chg_name;
+       #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+       ci->psy.type = POWER_SUPPLY_TYPE_UNKNOWN;
+       #else
+       ci->psy.type = -1;
+       #endif /* #ifdef (LINUX_VERSION_CODE */
+       ci->psy.supplied_to = rt_charger_supply_list;
+       ci->psy.properties = rt_charger_props;
+       ci->psy.num_properties = ARRAY_SIZE(rt_charger_props);
+       ci->psy.get_property = rt_charger_get_property;
+       ci->psy.set_property = rt_charger_set_property;
+       ret = power_supply_register(&pdev->dev, &ci->psy);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "couldn't create power supply for rt-charger\n");
+               goto out_dev;
+       }
+
+       #ifdef CONFIG_HAS_EARLYSUSPEND
+       ci->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 1;
+       ci->early_suspend.suspend = rt5025_charger_earlysuspend;
+       ci->early_suspend.resume = rt5025_charger_earlyresume;
+       register_early_suspend(&ci->early_suspend);
+       #endif /* CONFIG_HAS_EARLYSUSPEND */
+
+       #ifdef CONFIG_RT_POWER
+       rt_power_pdata = devm_kzalloc(&pdev->dev,
+               sizeof(*rt_power_pdata), GFP_KERNEL);
+       if (!rt_power_pdata) {
+               ret = -ENOMEM;
+               goto out_psy;
+       }
+       rt_power_pdata->chg_volt = ci->chg_volt;
+       rt_power_pdata->acchg_icc = ci->acchg_icc;
+       rt_power_pdata->usbtachg_icc = ci->usbtachg_icc;
+       rt_power_pdata->usbchg_icc = ci->usbchg_icc;
+
+       rt_power_dev.dev.platform_data = rt_power_pdata;
+       rt_power_dev.dev.parent = &pdev->dev;
+       ret = platform_device_register(&rt_power_dev);
+       if (ret < 0)
+               goto out_psy;
+       #endif /* #ifdef CONFIG_RT_POWER */
+
+       chip->charger_info = ci;
+       schedule_delayed_work(&ci->tempmon_work, 1*HZ);
+       dev_info(&pdev->dev, "driver successfully loaded\n");
+       return 0;
+#ifdef CONFIG_RT_POWER
+out_psy:
+#endif /* #ifdef CONFIG_RT_POWER */
+       #ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&ci->early_suspend);
+       #endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */
+       power_supply_unregister(&ci->psy);
+out_dev:
+       return ret;
+}
+
+static int rt5025_charger_remove(struct platform_device *pdev)
+{
+       struct rt5025_charger_info *ci = platform_get_drvdata(pdev);
+
+       power_supply_unregister(&ci->psy);
+       #ifdef CONFIG_HAS_EARLYSUSPEND
+       unregister_early_suspend(&ci->early_suspend);
+       #endif /* #ifdef CONFIG_HAS_EARLYSUSPEND */
+       #ifdef CONFIG_RT_POWER
+       platform_device_unregister(&rt_power_dev);
+       #endif /* #ifdef CONFIG_RT_POWER */
+       return 0;
+}
+
+static int rt5025_charger_suspend(struct platform_device *pdev,
+       pm_message_t state)
+{
+       struct rt5025_charger_info *ci = platform_get_drvdata(pdev);
+       union power_supply_propval pval;
+
+       ci->suspend = 1;
+       cancel_delayed_work_sync(&ci->tempmon_work);
+       /*force inttemp to normal temp*/
+       ci->inttemp_region = RT5025_INTTEMP_NORMAL;
+       pval.intval = 1;
+       rt_charger_set_property(&ci->psy, POWER_SUPPLY_PROP_PRESENT, &pval);
+       return 0;
+}
+
+static int rt5025_charger_resume(struct platform_device *pdev)
+{
+       struct rt5025_charger_info *ci = platform_get_drvdata(pdev);
+
+       ci->suspend = 0;
+       schedule_delayed_work(&ci->tempmon_work, msecs_to_jiffies(50));
+       return 0;
+}
+
+static const struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-charger",},
+       {},
+};
+
+static struct platform_driver rt5025_charger_driver = {
+       .driver = {
+               .name = RT5025_DEV_NAME "-charger",
+               .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
+       },
+       .probe = rt5025_charger_probe,
+       .remove = rt5025_charger_remove,
+       .suspend = rt5025_charger_suspend,
+       .resume = rt5025_charger_resume,
+};
+
+static int rt5025_charger_init(void)
+{
+       return platform_driver_register(&rt5025_charger_driver);
+}
+fs_initcall_sync(rt5025_charger_init);
+
+static void rt5025_charger_exit(void)
+{
+       platform_driver_unregister(&rt5025_charger_driver);
+}
+
+module_exit(rt5025_charger_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
+MODULE_DESCRIPTION("Charger driver for RT5025");
+MODULE_ALIAS("platform:"RT5025_DEV_NAME "-charger");
+MODULE_VERSION(RT5025_DRV_VER);
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 52e777c..62041ad
 #include <linux/mfd/rt5025.h>
 #include <linux/power/rt5025-swjeita.h>
 
-#define TEMP_TOLERANCE 30  // 'c*10 gap for tolerance
+#define TEMP_TOLERANCE 30  /*'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);
@@ -44,9 +45,9 @@ static int rt5025_set_charging_cc(struct i2c_client *i2c, int cur_value)
        if (cur_value < 500)
                data = 0;
        else if (cur_value > 2000)
-               data = 0xf<<RT5025_CHGICC_SHIFT;
+               data = 0xf << RT5025_CHGICC_SHIFT;
        else
-               data = ((cur_value-500)/100)<<RT5025_CHGICC_SHIFT;
+               data = ((cur_value - 500) / 100) << RT5025_CHGICC_SHIFT;
 
        ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL4, RT5025_CHGICC_MASK, data);
 
@@ -67,9 +68,9 @@ static int rt5025_set_charging_cv(struct i2c_client *i2c, int voltage)
        if (voltage < 3500)
                data = 0;
        else if (voltage > 4440)
-               data = 0x2f<<RT5025_CHGCV_SHIFT;
+               data = 0x2f << RT5025_CHGCV_SHIFT;
        else
-               data = ((voltage-3500)/20)<<RT5025_CHGCV_SHIFT;
+               data = ((voltage - 3500) / 20) << RT5025_CHGCV_SHIFT;
 
        ret = rt5025_assign_bits(i2c, RT5025_REG_CHGCTL3, RT5025_CHGCV_MASK, data);
        return ret;
@@ -101,53 +102,52 @@ 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;
+       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;
+       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;
@@ -185,65 +185,60 @@ static int rt5025_set_exttemp_alert(struct rt5025_swjeita_info *swji, int index)
 
        RTINFO("index = %d\n", index);
 
-       switch (index)
-       {
+       switch (index) {
+       case 0:
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
+               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[3]);
+               break;
+       case 2:
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[5]);
+               break;
+       case 3:
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[4]);
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[7]);
+               break;
+       case 4:
+               rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[6]);
+               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_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[1]);
+                       rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMNEN_MASK);
                        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[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 2:
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[2]);
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[5]);
+                       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_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[4]);
-                       rt5025_reg_write(swji->i2c, RT5025_REG_TALRTMIN, swji->temp_scalar[7]);
+                       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_reg_write(swji->i2c, RT5025_REG_TALRTMAX, swji->temp_scalar[6]);
+                       rt5025_set_bits(swji->i2c, RT5025_REG_IRQCTL, RT5025_TMXEN_MASK);
                        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;               
+       return 0;
 }
 
 int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_type)
@@ -256,34 +251,32 @@ int rt5025_notify_charging_cable(struct rt5025_swjeita_info *swji, int cable_typ
        rt5025_exttemp_alert_switch(swji, 0);
 
        sect_index = rt5025_get_external_temp_index(swji);
-       if (swji->cur_section != sect_index || swji->init_once == 0)
-       {
+       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]\
-                               - swji->dec_current);
-                       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]\
-                               - swji->dec_current);
-                       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]\
-                               - swji->dec_current);
-                       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;
+       switch (cable_type) {
+       case JEITA_NORMAL_USB:
+               rt5025_set_charging_cc(swji->i2c, swji->temp_cc[cable_type][swji->cur_section]\
+                       - swji->dec_current);
+               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]\
+                       - swji->dec_current);
+               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]\
+                       - swji->dec_current);
+               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;
 
@@ -298,7 +291,7 @@ int rt5025_swjeita_irq_handler(struct rt5025_swjeita_info *swji, unsigned char e
        int ret = 0;
        RTINFO("event = 0x%02x\n", event);
 
-       if (event&(RT5025_TMXEN_MASK|RT5025_TMNEN_MASK))
+       if (event&(RT5025_TMXEN_MASK | RT5025_TMNEN_MASK))
                rt5025_notify_charging_cable(swji, swji->cur_cable);
 
        return ret;
@@ -309,54 +302,51 @@ static void rt5025_get_internal_temp(struct rt5025_swjeita_info *swji)
 {
        u8 data[2];
        s32 temp;
-       if (rt5025_reg_block_read(swji->i2c, RT5025_REG_INTTEMP_MSB, 2, data) < 0){
+       if (rt5025_reg_block_read(swji->i2c, RT5025_REG_INTTEMP_MSB, 2, data) < 0)
                pr_err("%s: Failed to read internal TEMPERATURE\n", __func__);
-       }
 
-       temp = ((data[0]&0x1F)<<8) + data[1];
+       temp = ((data[0] & 0x1F) << 8) + data[1];
        temp *= 15625;
        temp /= 100000;
 
-       temp = (data[0]&0x20)?-temp:temp;
+       temp = (data[0] & 0x20) ? -temp : temp;
        swji->cur_inttemp = temp;
 
        RTINFO("internal temperature: %d\n", temp);
 }
-       
+
 static void thermal_reg_work_func(struct work_struct *work)
 {
        struct delayed_work *delayed_work = (struct delayed_work *)container_of(work, struct delayed_work, work);
        struct rt5025_swjeita_info *swji = (struct rt5025_swjeita_info *)container_of(delayed_work, struct rt5025_swjeita_info, thermal_reg_work);
        int therm_region = 0;
-       
+
        RTINFO("%s ++", __func__);
        rt5025_get_internal_temp(swji);
 
        #if 1
-       switch (swji->cur_therm_region)
-       {
-               case 0:
-                       if (swji->cur_inttemp >=820)
-                               therm_region = 1;
-                       else
-                               therm_region = 0;
-                       break;
-               case 1:
-                       if (swji->cur_inttemp <= 780)
-                               therm_region = 0;
-                       else if (swji->cur_inttemp >= 1020)
-                               therm_region = 2;
-                       else
-                               therm_region = 1; 
-                       break;
-               case 2:
-                       if (swji->cur_inttemp <= 980)
-                               therm_region = 1;
-                       else
-                               therm_region = 2;
-                       break;
-                       
-       }
+       switch (swji->cur_therm_region) {
+       case 0:
+               if (swji->cur_inttemp >= 820)
+                       therm_region = 1;
+               else
+                       therm_region = 0;
+               break;
+       case 1:
+               if (swji->cur_inttemp <= 780)
+                       therm_region = 0;
+               else if (swji->cur_inttemp >= 1020)
+                       therm_region = 2;
+               else
+                       therm_region = 1;
+               break;
+       case 2:
+               if (swji->cur_inttemp <= 980)
+                       therm_region = 1;
+               else
+                       therm_region = 2;
+               break;
+               }
        #else
        if (swji->cur_inttemp < 800)
                therm_region = 0;
@@ -366,19 +356,17 @@ static void thermal_reg_work_func(struct work_struct *work)
                therm_region = 2;
        #endif /* #if 1*/
 
-       if (therm_region != swji->cur_therm_region)
-       {
-               switch (therm_region)
-               {
-                       case 0:
-                               swji->dec_current = 0;
-                               break;
-                       case 1:
-                               swji->dec_current = 300;
-                               break;
-                       case 2:
-                               swji->dec_current = 800;
-                               break;
+       if (therm_region != swji->cur_therm_region) {
+               switch (therm_region) {
+               case 0:
+                       swji->dec_current = 0;
+                       break;
+               case 1:
+                       swji->dec_current = 300;
+                       break;
+               case 2:
+                       swji->dec_current = 800;
+                       break;
                }
                swji->cur_therm_region = therm_region;
                rt5025_notify_charging_cable(swji, swji->cur_cable);
@@ -390,10 +378,10 @@ static void thermal_reg_work_func(struct work_struct *work)
        RTINFO("%s --", __func__);
 }
 
-static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
+static int 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_platform_data *pdata = chip->dev->platform_data;
        struct rt5025_swjeita_info *swji;
        int ret = 0;
 
@@ -401,23 +389,20 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
        if (!swji)
                return -ENOMEM;
 
-       #if 0 // for debug pdata->jeita_data
-       for (ret=0; ret<4; ret++)
+       #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++)
-       {
+       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++)
-       {
+       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<8; ret++)
-       {
+       for (ret = 0; ret < 8; ret++) {
                RTINFO("temp_scalar[%d] = 0x%02x\n", ret, pdata->jeita_data->temp_scalar[ret]);
        }
        ret = 0;
@@ -425,7 +410,8 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
 
        swji->i2c = chip->i2c;
        swji->chip = chip;
-       swji->cur_section = 2; //initial as the normal temperature
+       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;
@@ -445,7 +431,7 @@ static int __devinit rt5025_swjeita_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
+static int rt5025_swjeita_remove(struct platform_device *pdev)
 {
        struct rt5025_swjeita_info *swji = platform_get_drvdata(pdev);
 
@@ -458,6 +444,7 @@ static int __devexit rt5025_swjeita_remove(struct platform_device *pdev)
 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;
        cancel_delayed_work_sync(&swji->thermal_reg_work);
        swji->cur_therm_region = swji->dec_current = 0;
@@ -476,8 +463,7 @@ static int rt5025_swjeita_resume(struct platform_device *pdev)
        return 0;
 }
 
-static struct platform_driver rt5025_swjeita_driver = 
-{
+static struct platform_driver rt5025_swjeita_driver = {
        .driver = {
                .name = RT5025_DEVICE_NAME "-swjeita",
                .owner = THIS_MODULE,
@@ -488,13 +474,13 @@ static struct platform_driver rt5025_swjeita_driver =
        .resume = rt5025_swjeita_resume,
 };
 
-static int __init rt5025_swjeita_init(void)
+static int rt5025_swjeita_init(void)
 {
        return platform_driver_register(&rt5025_swjeita_driver);
 }
 module_init(rt5025_swjeita_init);
 
-static void __exit rt5025_swjeita_exit(void)
+static void rt5025_swjeita_exit(void)
 {
        platform_driver_unregister(&rt5025_swjeita_driver);
 }
index a55583ce50128a8b30e86228e11486bf5241bd14..13e1a2f433c7012116025322d8e426e7b5d5de27 100755 (executable)
@@ -262,6 +262,13 @@ config ACT8846_SUPPORT_RESET
        help
          Support short press key to restart.
 
+config REGULATOR_RT5025
+       bool "Richtek RT5025 PMIC Voltage regulstors"
+       depends on MFD_RT5025
+       default n
+       help
+         This driver supports voltage regulator in RT5025 PMIC chips.
+
 config ROCKCHIP_PWM_REGULATOR
        tristate "rockchip pwm voltage regulator for discrete dcdc or ldo"
        help
index e81fad7415c86eae7c1c1773e800162598990a45..153030939736b3498e1337db500071746ae41d03 100755 (executable)
@@ -76,6 +76,7 @@ obj-$(CONFIG_REGULATOR_WM8994) += wm8994-regulator.o
 obj-$(CONFIG_REGULATOR_ACT8846) += act8846.o
 obj-$(CONFIG_REGULATOR_SYR82X) += syr82x.o
 obj-$(CONFIG_REGULATOR_RICOH619) += ricoh619-regulator.o
+obj-$(CONFIG_REGULATOR_RT5025) += rt5025-regulator.o
 
 obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip_io_vol_domain.o
 
index 46f7c7a0bec51bd868e7216cae0290e14977ebce..eabbe5cce544906e7971463ec4de1ed127da3412 100755 (executable)
@@ -2,12 +2,13 @@
  *  drivers/regulator/rt5025-regulator.c
  *  Driver foo Richtek RT5025 PMIC Regulator
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2014 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #include <linux/module.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/driver.h>
 #include <linux/version.h>
+#ifdef CONFIG_OF
+#include <linux/regulator/of_regulator.h>
+#endif /* #ifdef CONFIG_OF */
+
 #include <linux/mfd/rt5025.h>
 #include <linux/regulator/rt5025-regulator.h>
 
@@ -25,7 +30,6 @@ struct rt5025_regulator_info {
        struct regulator_desc   desc;
        struct regulator_dev    *regulator;
        struct i2c_client       *i2c;
-       struct rt5025_chip      *chip;
        const unsigned int      *vol_output_list;
        const int               vol_output_size;
        int     min_uV;
@@ -37,11 +41,12 @@ struct rt5025_regulator_info {
        int     enable_reg;
        int     mode_bit;
        int     mode_reg;
+       int     ramp_bit;
+       int     ramp_reg;
 };
 
-//for DCDC1
-static const unsigned int rt5025_vol_output_list1[] =
-{
+/*for DCDC1*/
+static const unsigned int rt5025_vol_output_list1[] = {
         700*1000,  725*1000,  750*1000,  775*1000,  800*1000,  825*1000,  850*1000,  875*1000,
         900*1000,  925*1000,  950*1000,  975*1000, 1000*1000, 1025*1000, 1050*1000, 1075*1000,
        1100*1000, 1125*1000, 1150*1000, 1175*1000, 1200*1000, 1225*1000, 1250*1000, 1275*1000,
@@ -53,9 +58,8 @@ static const unsigned int rt5025_vol_output_list1[] =
 };
 #define rt5025_vol_output_size1 ARRAY_SIZE(rt5025_vol_output_list1)
 
-//DCDC2, LDO1, LDO2
-static const unsigned int rt5025_vol_output_list2[] =
-{
+/*DCDC2, LDO1, LDO2*/
+static const unsigned int rt5025_vol_output_list2[] = {
         700*1000,  725*1000,  750*1000,  775*1000,  800*1000,  825*1000,  850*1000,  875*1000,
         900*1000,  925*1000,  950*1000,  975*1000, 1000*1000, 1025*1000, 1050*1000, 1075*1000,
        1100*1000, 1125*1000, 1150*1000, 1175*1000, 1200*1000, 1225*1000, 1250*1000, 1275*1000,
@@ -75,9 +79,8 @@ static const unsigned int rt5025_vol_output_list2[] =
 };
 #define rt5025_vol_output_size2 ARRAY_SIZE(rt5025_vol_output_list2)
 
-//DCDC3
-static const unsigned int rt5025_vol_output_list3[] =
-{
+/*DCDC3*/
+static const unsigned int rt5025_vol_output_list3[] = {
         700*1000,  750*1000,  800*1000,  850*1000,  900*1000,  950*1000, 1000*1000, 1050*1000,
        1100*1000, 1150*1000, 1200*1000, 1250*1000, 1300*1000, 1350*1000, 1400*1000, 1450*1000,
        1500*1000, 1550*1000, 1600*1000, 1650*1000, 1700*1000, 1750*1000, 1800*1000, 1850*1000,
@@ -89,17 +92,15 @@ static const unsigned int rt5025_vol_output_list3[] =
 };
 #define rt5025_vol_output_size3 ARRAY_SIZE(rt5025_vol_output_list3)
 
-//DCDC4
-static const unsigned int rt5025_vol_output_list4[] =
-{
+/*DCDC4*/
+static const unsigned int rt5025_vol_output_list4[] = {
        4500*1000, 4600*1000, 4700*1000, 4800*1000, 4900*1000, 5000*1000, 5100*1000, 5200*1000,
        5300*1000, 5400*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000, 5500*1000,
 };
 #define rt5025_vol_output_size4 ARRAY_SIZE(rt5025_vol_output_list4)
 
-//LDO3, LDO4, LDO5, LDO6
-static const unsigned int rt5025_vol_output_list5[] = 
-{
+/*LDO3, LDO4, LDO5, LDO6*/
+static const unsigned int rt5025_vol_output_list5[] = {
        1000*1000, 1100*1000, 1200*1000, 1300*1000, 1400*1000, 1500*1000, 1600*1000, 1700*1000,
        1800*1000, 1900*1000, 2000*1000, 2100*1000, 2200*1000, 2300*1000, 2400*1000, 2500*1000,
        2600*1000, 2700*1000, 2800*1000, 2900*1000, 3000*1000, 3100*1000, 3200*1000, 3300*1000,
@@ -121,29 +122,29 @@ static int rt5025_list_voltage(struct regulator_dev *rdev, unsigned index)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
 
-       return (index>=info->vol_output_size)? \
-                -EINVAL: \
-               info->vol_output_list[index];
+       return (index >= info->vol_output_size) ? -EINVAL : info->vol_output_list[index];
 }
 
-#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
+#if (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);
        unsigned char data;
        const int count = info->vol_output_size;
 
-       if (selector>count)
+       if (selector > count)
                return -EINVAL;
        data = (unsigned char)selector;
        data <<= info->vol_shift;
-       return rt5025_assign_bits(info->i2c, info->vol_reg, info->vol_mask, data);
+       return rt5025_assign_bits(info->i2c, info->vol_reg,
+               info->vol_mask, data);
 }
 
 static int rt5025_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
        int ret;
+
        ret = rt5025_reg_read(info->i2c, info->vol_reg);
        if (ret < 0)
                return ret;
@@ -154,12 +155,12 @@ static int rt5025_find_voltage(struct regulator_dev *rdev,
                               int min_uV, int max_uV)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
-       int i=0;
+       int i = 0;
        const int count = info->vol_output_size;
-       for (i=0;i<count;i++)
-       {
-               if ((info->vol_output_list[i]>=min_uV)
-                       && (info->vol_output_list[i]<=max_uV))
+
+       for (i = 0; i < count; i++) {
+               if ((info->vol_output_list[i] >= min_uV)
+                       && (info->vol_output_list[i] <= max_uV))
                        return i;
        }
        return -EINVAL;
@@ -167,20 +168,20 @@ static int rt5025_find_voltage(struct regulator_dev *rdev,
 
 static int rt5025_set_voltage(struct regulator_dev *rdev,
                               int min_uV, int max_uV, unsigned *selector)
-       
 {
        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",
+               dev_err(&rdev->dev, "invalid voltage range (%d, %d) uV\n",
                        min_uV, max_uV);
                return -EINVAL;
        }
-       data = rt5025_find_voltage(rdev,min_uV,max_uV);
+       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);
+       return rt5025_assign_bits(info->i2c, info->vol_reg,
+               info->vol_mask, data);
 }
 
 
@@ -188,6 +189,7 @@ static int rt5025_get_voltage(struct regulator_dev *rdev)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
        int ret;
+
        ret = rt5025_reg_read(info->i2c, info->vol_reg);
        if (ret < 0)
                return ret;
@@ -220,29 +222,29 @@ static int rt5025_is_enabled(struct regulator_dev *rdev)
        ret = rt5025_reg_read(info->i2c, info->enable_reg);
        if (ret < 0)
                return ret;
-
-       return (ret & (info->enable_bit))?1:0;
+       return (ret & (info->enable_bit))?1 : 0;
 }
 
 static int rt5025_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct rt5025_regulator_info *info = rdev_get_drvdata(rdev);
        int ret;
-       if (!info->mode_bit)
+
+       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;
+       } 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;
@@ -254,19 +256,18 @@ static unsigned int rt5025_get_mode(struct regulator_dev *rdev)
        unsigned int mode;
        int data;
 
-       if (!info->mode_bit)
+       if (!info->mode_bit) {
                mode = REGULATOR_MODE_NORMAL;
-       else
-       {
+       } else {
                data = rt5025_reg_read(info->i2c, info->mode_reg);
-               mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL:REGULATOR_MODE_FAST;
+               mode = (data & info->mode_bit)?REGULATOR_MODE_NORMAL : REGULATOR_MODE_FAST;
        }
        return mode;
 }
 
 static struct regulator_ops rt5025_regulator_ops = {
        .list_voltage           = rt5025_list_voltage,
-#if 0 //(LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,38))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 38))
        .get_voltage_sel        = rt5025_get_voltage_sel,
        .set_voltage_sel        = rt5025_set_voltage_sel,
 #else
@@ -306,24 +307,26 @@ static struct regulator_ops rt5025_regulator_ops = {
 #define RT5025_DCDC(_id, min, max)                             \
 {                                                              \
        .desc   = {                                             \
-               .name   = "rt5025-dcdc" #_id,   \
+               .name   = "rt5025-dcdc" #_id,                   \
                .n_voltages = RT5025_DCDCVOUT_SIZE##_id,        \
                .ops    = &rt5025_regulator_ops,                \
                .type   = REGULATOR_VOLTAGE,                    \
                .id     = RT5025_ID_DCDC##_id,                  \
                .owner  = THIS_MODULE,                          \
        },                                                      \
-       .vol_output_list= RT5025_DCDCVOUT_LIST##_id,            \
-       .vol_output_size= RT5025_DCDCVOUT_SIZE##_id,            \
-       .min_uV         = min ,                         \
-       .max_uV         = max ,                         \
+       .vol_output_list = RT5025_DCDCVOUT_LIST##_id,           \
+       .vol_output_size = RT5025_DCDCVOUT_SIZE##_id,           \
+       .min_uV         = min * 1000,                           \
+       .max_uV         = max * 1000,                           \
        .vol_reg        = RT5025_DCDCVOUT##_id,                 \
        .vol_shift      = RT5025_DCDCVOUT_SHIFT##_id,           \
        .vol_mask       = RT5025_DCDCVOUT_MASK##_id,            \
-       .enable_reg     = RT5025_DCDC_OUTPUT_EN,                \
+       .enable_reg     = RT5025_REG_DCDCONOFF,                 \
        .enable_bit     = RT5025_DCDCEN_MASK##_id,              \
-       .mode_reg       = RT5025_REG_DCDCVRC,                   \
-       .mode_bit       = RT5025_DCDCMODE_MASK##_id             \
+       .mode_reg       = RT5025_DCDCMODE_REG##_id,             \
+       .mode_bit       = RT5025_DCDCMODE_MASK##_id,            \
+       .ramp_reg       = RT5025_DCDCVOUT##_id,                 \
+       .ramp_bit       = RT5025_DCDCRAMP_MASK##_id,            \
 }
 
 #define RT5025_LDO(_id, min, max)                              \
@@ -336,34 +339,31 @@ static struct regulator_ops rt5025_regulator_ops = {
                .id     = RT5025_ID_LDO##_id,                   \
                .owner  = THIS_MODULE,                          \
        },                                                      \
-       .vol_output_list= RT5025_LDOVOUT_LIST##_id,             \
-       .vol_output_size= RT5025_LDOVOUT_SIZE##_id,             \
-       .min_uV         = min ,                         \
-       .max_uV         = max,                          \
+       .vol_output_list = RT5025_LDOVOUT_LIST##_id,            \
+       .vol_output_size = RT5025_LDOVOUT_SIZE##_id,            \
+       .min_uV         = min * 1000,                           \
+       .max_uV         = max * 1000,                           \
        .vol_reg        = RT5025_LDOVOUT##_id,                  \
        .vol_shift      = RT5025_LDOVOUT_SHIFT##_id,            \
        .vol_mask       = RT5025_LDOVOUT_MASK##_id,             \
-       .enable_reg     = RT5025_LDO_OUTPUT_EN,                 \
+       .enable_reg     = RT5025_REG_LDOONOFF,                  \
        .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[] = 
-{
-       RT5025_DCDC(1,  700000, 2275000),
-       RT5025_DCDC(2,  700000, 3500000),
-       RT5025_DCDC(3,  700000, 3500000),
-       RT5025_DCDC(4, 4500000, 5500000),
-       RT5025_LDO( 1,  700000, 3500000),
-       RT5025_LDO( 2,  700000, 3500000),
-       RT5025_LDO( 3, 1000000, 3300000),
-       RT5025_LDO( 4, 1000000, 3300000),
-       RT5025_LDO( 5, 1000000, 3300000),
-       RT5025_LDO( 6, 1000000, 3300000),
+static struct rt5025_regulator_info rt5025_regulator_info[] = {
+       RT5025_DCDC(1, 700, 2275),
+       RT5025_DCDC(2, 700, 3500),
+       RT5025_DCDC(3, 700, 3500),
+       RT5025_DCDC(4, 4500, 5500),
+       RT5025_LDO(1, 700, 3500),
+       RT5025_LDO(2, 700, 3500),
+       RT5025_LDO(3, 1000, 3300),
+       RT5025_LDO(4, 1000, 3300),
+       RT5025_LDO(5, 1000, 3300),
+       RT5025_LDO(6, 1000, 3300),
 };
 
-static struct rt5025_regulator_info * __devinit find_regulator_info(int id)
+static struct rt5025_regulator_info *find_regulator_info(int id)
 {
        struct rt5025_regulator_info *ri;
        int i;
@@ -375,43 +375,87 @@ static struct rt5025_regulator_info * __devinit find_regulator_info(int id)
        }
        return NULL;
 }
-
-inline struct regulator_dev* rt5025_regulator_register(struct regulator_desc *regulator_desc,
-            struct device *dev, struct regulator_init_data *init_data,
-            void *driver_data)
+struct regulator_dev *rt5025_regulator_register(struct regulator_desc *regulator_desc,
+       struct device *dev, struct regulator_init_data *init_data,
+       void *driver_data)
 {
-#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,5,0))
-    struct regulator_config config = {
-        .dev = dev,
-        .init_data = init_data,
-        .driver_data = driver_data,
-    };
-    return regulator_register(&regulator_desc, &config);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
+       struct regulator_config config = {
+               .dev = dev,
+               .init_data = init_data,
+               .driver_data = driver_data,
+               .of_node = dev->of_node,
+       };
+       return regulator_register(regulator_desc, &config);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 37))
+       return regulator_register(regulator_desc, dev, init_data,
+               driver_data, dev->of_node);
 #else
-    return regulator_register(regulator_desc,dev,init_data,driver_data);
+       return regulator_register(regulator_desc, dev, init_data, driver_data);
 #endif /* LINUX_VERSION_CODE>=KERNEL_VERSION(3,5,0)) */
 }
 
-static int __devinit rt5025_regulator_probe(struct platform_device *pdev)
+static struct regulator_init_data *of_parse_dt(struct rt5025_regulator_info *ri,
+       struct device *dev)
+{
+       struct regulator_init_data *init_data = NULL;
+       #ifdef CONFIG_OF
+       struct device_node *np = dev->of_node;
+       int rc;
+       u32 tmp;
+       #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
+       init_data = of_get_regulator_init_data(dev, dev->of_node);
+       #else
+       init_data = of_get_regulator_init_data(dev);
+       #endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)) */
+       rc = of_property_read_u32(np, "rt,ramp_sel", &tmp);
+       if (rc) {
+               dev_info(dev, "no ramp_sel property, use default value\n");
+       } else {
+               if (tmp > RT5025_DCDCRAMP_MAX)
+                       tmp = RT5025_DCDCRAMP_MAX;
+               rt5025_assign_bits(ri->i2c, ri->ramp_reg, ri->ramp_bit, tmp);
+       }
+
+       if (of_property_read_bool(np, "rt,allow_mode_mask")) {
+               init_data->constraints.valid_modes_mask |=
+                       (REGULATOR_MODE_FAST|\
+                       REGULATOR_MODE_NORMAL);
+               init_data->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
+       }
+       #endif /* #ifdef CONFIG_OF */
+       return init_data;
+}
+
+static int rt5025_regulator_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_platform_data *pdata = (pdev->dev.parent)->platform_data;
        struct rt5025_regulator_info *ri;
+       struct rt5025_regulator_ramp *ramp;
        struct regulator_dev *rdev;
-       struct regulator_init_data* init_data;
+       struct regulator_init_data *init_data;
+       bool use_dt = pdev->dev.of_node;
 
        ri = find_regulator_info(pdev->id);
        if (ri == NULL) {
                dev_err(&pdev->dev, "invalid regulator ID specified\n");
                return -EINVAL;
        }
-       init_data = pdata->regulator[pdev->id];
-       if (init_data == NULL) {
+       ri->i2c = chip->i2c;
+       if (use_dt) {
+               init_data = of_parse_dt(ri, &pdev->dev);
+       } else {
+               init_data = pdata->regulator[pdev->id];
+               ramp = init_data->driver_data;
+               if (ramp)
+                       rt5025_assign_bits(ri->i2c, ri->ramp_reg,
+                               ri->ramp_bit, ramp->ramp_sel);
+       }
+       if (!init_data) {
                dev_err(&pdev->dev, "no initializing data\n");
                return -EINVAL;
        }
-       ri->i2c = chip->i2c;
-       ri->chip = chip;
 
        rdev = rt5025_regulator_register(&ri->desc, &pdev->dev,
                                  init_data, ri);
@@ -420,46 +464,59 @@ static int __devinit rt5025_regulator_probe(struct platform_device *pdev)
                                ri->desc.name);
                return PTR_ERR(rdev);
        }
-
        platform_set_drvdata(pdev, rdev);
-
+/*     dev_info(&pdev->dev, "driver successfully loaded\n");*/
        return 0;
 }
 
-static int __devexit rt5025_regulator_remove(struct platform_device *pdev)
+static int rt5025_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
        platform_set_drvdata(pdev, NULL);
        regulator_unregister(rdev);
-
+       dev_info(&pdev->dev, "%s\n", __func__);
        return 0;
 }
 
-static struct platform_driver rt5025_regulator_driver = 
-{
+static struct of_device_id rt_match_table[] = {
+       { .compatible = "rt,rt5025-dcdc1",},
+       { .compatible = "rt,rt5025-dcdc2",},
+       { .compatible = "rt,rt5025-dcdc3",},
+       { .compatible = "rt,rt5025-dcdc4",},
+       { .compatible = "rt,rt5025-ldo1",},
+       { .compatible = "rt,rt5025-ldo2",},
+       { .compatible = "rt,rt5025-ldo3",},
+       { .compatible = "rt,rt5025-ldo4",},
+       { .compatible = "rt,rt5025-ldo5",},
+       { .compatible = "rt,rt5025-ldo6",},
+       {},
+};
+
+static struct platform_driver rt5025_regulator_driver = {
        .driver = {
-               .name = RT5025_DEVICE_NAME "-regulator",
+               .name = RT5025_DEV_NAME "-regulator",
                .owner = THIS_MODULE,
+               .of_match_table = rt_match_table,
        },
        .probe = rt5025_regulator_probe,
-       .remove = __devexit_p(rt5025_regulator_remove),
+       .remove = rt5025_regulator_remove,
 };
 
-static int __init rt5025_regulator_init(void)
+static int rt5025_regulator_init(void)
 {
        return platform_driver_register(&rt5025_regulator_driver);
 }
-subsys_initcall_sync(rt5025_regulator_init);
+subsys_initcall(rt5025_regulator_init);
 
-static void __exit rt5025_regulator_exit(void)
+static void rt5025_regulator_exit(void)
 {
        platform_driver_unregister(&rt5025_regulator_driver);
 }
 module_exit(rt5025_regulator_exit);
 
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("CY Huang <cy_huang@richtek.com");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("CY Huang <cy_huang@richtek.com>");
 MODULE_DESCRIPTION("Regulator driver for RT5025");
-MODULE_ALIAS("platform:" RT5025_DEVICE_NAME "-regulator");
+MODULE_ALIAS("platform:" RT5025_DEV_NAME "-regulator");
 MODULE_VERSION(RT5025_DRV_VER);
index 0215077a7978712e38cfc06a1cabe29a5d663e1c..04ba1370c67c3b1bd4d9f6b24a025c738768ad99 100755 (executable)
@@ -1,26 +1,21 @@
 /*
- *  include/linux/mfd/rt5025-gpio.h
+ *  include/linux/mfd/rt5025/rt5025-gpio.h
  *  Include header file for Richtek RT5025 PMIC GPIO file
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2013 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #ifndef __LINUX_RT5025_GPIO_H
 #define __LINUX_RT5025_GPIO_H
 
-#define RT5025_REG_GPIO0 0x1C
-#define RT5025_REG_GPIO1 0x1D
-#define RT5025_REG_GPIO2 0x1E
-
-#define RT5025_GPIO_NR 3
-
-#define RT5025_GPIO_INPUT      0x00
-#define RT5025_GPIO_OUTPUT     0x02
+#define RT5025_GPIO_INPUT      0x00
+#define RT5025_GPIO_OUTPUT             0x02
 
 #define RT5025_GPIO_DIRSHIFT 6
 #define RT5025_GPIO_DIRMASK  0xC0
old mode 100644 (file)
new mode 100755 (executable)
index d826b2f..66a7f05
@@ -1,39 +1,19 @@
 /*
- *  include/linux/mfd/rt5025-irq.h
+ *  include/linux/mfd/rt5025/rt5025-irq.h
  *  Include header file for Richtek RT5025 PMIC IRQ file
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2014 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #ifndef __LINUX_RT5025_IRQ_H
 #define __LINUX_RT5025_IRQ_H
 
-#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_INACIRQ_MASK    0x40
-#define RT5025_INUSBIRQ_MASK   0x08
-#define RT5025_ADAPIRQ_MASK    (RT5025_INACIRQ_MASK|RT5025_INUSBIRQ_MASK)
-#define RT5025_CHTERMI_MASK    0x01
-
-#define RT5025_REG_GAUGEIRQEN  0x50
-#define RT5025_REG_GAUGEIRQFLG 0x51
-#define RT5025_FLG_TEMP                0x30
-#define RT5025_FLG_VOLT                0x07
+#define RT5025_TALRT_MASK 0x30
 
 #endif /* #ifndef __LINUX_RT5025_IRQ_H */
old mode 100644 (file)
new mode 100755 (executable)
index 20cadd2..8db2ab7
@@ -1,5 +1,5 @@
 /*
- *  include/linux/mfd/rt5025-misc.h
+ *  include/linux/mfd/rt5025/rt5025-misc.h
  *  Include header file for Richtek RT5025 PMIC Misc
  *
  *  Copyright (C) 2013 Richtek Technology Corp.
 #ifndef __LINUX_RT5025_MISC_H
 #define __LINUX_RT5025_MISC_H
 
-#define RT5025_RESETCTRL_REG   0x15
-#define RT5025_VSYSULVO_REG    0x17
-#define RT5025_PWRONCTRL_REG   0x19
-#define RT5025_SHDNCTRL_REG    0x1A
-#define RT5025_PWROFFEN_REG    0x1B
-#define RT5025_CHENH_REG       0x62
-#define RT5025_CHENL_REG       0x63
+enum {
+       MISCEVENT_GPIO0_IE = 1,
+       MISCEVENT_GPIO1_IE,
+       MISCEVENT_GPIO2_IE,
+       MISCEVENT_RESETB,
+       MISCEVENT_PWRONF,
+       MISCEVENT_PWRONR,
+       MISCEVENT_KPSHDN,
+       MISCEVENT_SYSLV,
+       MISCEVENT_DCDC4LVHV,
+       MISCEVENT_PWRONLP_IRQ,
+       MISCEVENT_PWRONSP_IRQ,
+       MISCEVENT_DCDC3LV,
+       MISCEVENT_DCDC2LV,
+       MISCEVENT_DCDC1LV,
+       MISCEVENT_OT,
+       MISCEVENT_MAX,
+};
 
 #define RT5025_SHDNCTRL_MASK   0x80
 #define RT5025_VSYSOFF_MASK    0xE0
+#define RT5025_VSYSOFF_SHFT    5
+#define RT5025_SHDNLPRESS_MASK 0x0C
+#define RT5025_SHDNLPRESS_SHFT 2
+#define RT5025_STARTLPRESS_MASK        0xC0
+#define RT5025_STARTLPRESS_SHFT        6
+#define RT5025_VSYSLVSHDN_MASK 0x80
+#define RT5025_VSYSLVSHDN_SHFT 7
+#define RT5025_CABLEIN_MASK    0x03
+
+extern int rt5025_cable_exist(void);
 
 #endif /* #ifndef __LINUX_RT5025_MISC_H */
old mode 100644 (file)
new mode 100755 (executable)
index 3d5ba95..961c639
 /*
- *  include/linux/mfd/rt5025.h
+ *  include/linux/mfd/rt5025/rt5025.h
  *  Include header file for Richtek RT5025 Core file
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2013 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #ifndef __LINUX_MFD_RT5025_H
 #define __LINUX_MFD_RT5025_H
 
 #include <linux/power_supply.h>
-#include <linux/android_alarm.h>
+#include <linux/alarmtimer.h>
+#include <linux/wakelock.h>
+#ifdef CONFIG_HAS_EARLYSUSPEND
+#include <linux/earlysuspend.h>
+#endif /* CONFIG_HAS_EARLYSUSPEND */
 
-#define RT5025_DEVICE_NAME "RT5025"
-#define RT5025_DRV_VER    "1.0.8_R"
+#define RT5025_DEV_NAME "rt5025"
+#define RT5025_DRV_VER    "1.1.0_R"
 
-enum {
-       RT5025_RSTDELAY1_100MS,
-       RT5025_RSTDELAY1_500MS,
-       RT5025_RSTDELAY1_1S,
-       RT5025_RSTDELAY1_2S,
-};
+#define RT_BATT_NAME   "rt-battery"
 
 enum {
-       RT5025_RSTDELAY2_100MS,
-       RT5025_RSTDELAY2_500MS,
-       RT5025_RSTDELAY2_1S,
-       RT5025_RSTDELAY2_2S,
+       RT5025_REG_DEVID,
+       RT5025_REG_RANGE1START = RT5025_REG_DEVID,
+       RT5025_REG_CHGCTL1,
+       RT5025_REG_CHGCTL2,
+       RT5025_REG_CHGCTL3,
+       RT5025_REG_CHGCTL4,
+       RT5025_REG_CHGCTL5,
+       RT5025_REG_CHGCTL6,
+       RT5025_REG_CHGCTL7,
+       RT5025_REG_DCDCCTL1,
+       RT5025_REG_DCDCCTL2,
+       RT5025_REG_DCDCCTL3,
+       RT5025_REG_VRCCTL,
+       RT5025_REG_DCDCCTL4,
+       RT5025_REG_LDOCTL1,
+       RT5025_REG_LDOCTL2,
+       RT5025_REG_LDOCTL3,
+       RT5025_REG_LDOCTL4,
+       RT5025_REG_LDOCTL5,
+       RT5025_REG_LDOCTL6,
+       RT5025_REG_RESV0,
+       RT5025_REG_LDOOMS,
+       RT5025_REG_MISC1,
+       RT5025_REG_ONEVENT,
+       RT5025_REG_DCDCONOFF,
+       RT5025_REG_LDOONOFF,
+       RT5025_REG_MISC2,
+       RT5025_REG_MISC3,
+       RT5025_REG_MISC4,
+       RT5025_REG_GPIO0,
+       RT5025_REG_GPIO1,
+       RT5025_REG_GPIO2,
+       RT5025_REG_RANGE1END = RT5025_REG_GPIO2,
+       RT5025_REG_OFFEVENT = 0x20,
+       RT5025_REG_RANGE2START = RT5025_REG_OFFEVENT,
+       RT5025_REG_RESV1,
+       RT5025_REG_RESV2,
+       RT5025_REG_RESV3,
+       RT5025_REG_RESV4,
+       RT5025_REG_RESV5,
+       RT5025_REG_RESV6,
+       RT5025_REG_RESV7,
+       RT5025_REG_RESV8,
+       RT5025_REG_RESV9,
+       RT5025_REG_RESV10,
+       RT5025_REG_RESV11,
+       RT5025_REG_RESV12,
+       RT5025_REG_RESV13,
+       RT5025_REG_RESV14,
+       RT5025_REG_RESV15,
+       RT5025_REG_IRQEN1,
+       RT5025_REG_IRQSTAT1,
+       RT5025_REG_IRQEN2,
+       RT5025_REG_IRQSTAT2,
+       RT5025_REG_IRQEN3,
+       RT5025_REG_IRQSTAT3,
+       RT5025_REG_IRQEN4,
+       RT5025_REG_IRQSTAT4,
+       RT5025_REG_IRQEN5,
+       RT5025_REG_IRQSTAT5,
+       RT5025_REG_RANGE2END = RT5025_REG_IRQSTAT5,
+       RT5025_REG_IRQCTL = 0x50,
+       RT5025_REG_RANGE3START = RT5025_REG_IRQCTL,
+       RT5025_REG_IRQFLG,
+       RT5025_REG_FGRESV1,
+       RT5025_REG_VALRTMAX,
+       RT5025_REG_VALRTMIN1,
+       RT5025_REG_VALRTMIN2,
+       RT5025_REG_TALRTMAX,
+       RT5025_REG_TALRTMIN,
+       RT5025_REG_VBATSH,
+       RT5025_REG_VBATSL,
+       RT5025_REG_INTEMPH,
+       RT5025_REG_INTEMPL,
+       RT5025_REG_FGRESV2,
+       RT5025_REG_CONFIG,
+       RT5025_REG_AINH,
+       RT5025_REG_AINL,
+       RT5025_REG_TIMERH,
+       RT5025_REG_TIMERL,
+       RT5025_REG_CHANNELH,
+       RT5025_REG_CHANNELL,
+       RT5025_REG_INACVLTH,
+       RT5025_REG_INACVLTL,
+       RT5025_REG_INUSBVLTH,
+       RT5025_REG_INUSBVLTL,
+       RT5025_REG_VSYSVLTH,
+       RT5025_REG_VSYSVLTL,
+       RT5025_REG_GPIO0VLTH,
+       RT5025_REG_GPIO0VLTL,
+       RT5025_REG_GPIO1VLTH,
+       RT5025_REG_GPIO1VLTL,
+       RT5025_REG_GPIO2VLTH,
+       RT5025_REG_GPIO2VLTL,
+       RT5025_REG_DCDC1VLTH,
+       RT5025_REG_DCDC1VLTL,
+       RT5025_REG_DCDC2VLTH,
+       RT5025_REG_DCDC2VLTL,
+       RT5025_REG_DCDC3VLTH,
+       RT5025_REG_DCDC3VLTL,
+       RT5025_REG_CURRH,
+       RT5025_REG_CURRL,
+       RT5025_REG_QCHGHH,
+       RT5025_REG_QCHGHL,
+       RT5025_REG_QCHGLH,
+       RT5025_REG_QCHGLL,
+       RT5025_REG_QDCHGHH,
+       RT5025_REG_QDCHGHL,
+       RT5025_REG_QDCHGLH,
+       RT5025_REG_QDCHGLL,
+       RT5025_REG_RANGE3END = RT5025_REG_QDCHGLL,
+       RT5025_REG_DCDC4OVP = 0xA9,
+       RT5025_REG_RANGE4START = RT5025_REG_DCDC4OVP,
+       RT5025_REG_RANGE4END = RT5025_REG_DCDC4OVP,
+       RT5025_REG_MAX,
 };
 
 enum {
@@ -42,6 +153,7 @@ enum {
        RT5025_VOFF_3P3V,
        RT5025_VOFF_3P4V,
        RT5025_VOFF_3P5V,
+       RT5025_VOFF_MAX = RT5025_VOFF_3P5V,
 };
 
 enum {
@@ -49,13 +161,7 @@ enum {
        RT5025_STARTIME_1S,
        RT5025_STARTIME_2S,
        RT5025_STARTIME_3S,
-};
-
-enum {
-       RT5025_LPRESS_1S,
-       RT5025_LPRESS_1P5S,
-       RT5025_LPRESS_2S,
-       RT5025_LPRESS_2P5S,
+       RT5025_STARTIME_MAX = RT5025_STARTIME_3S,
 };
 
 enum {
@@ -63,68 +169,21 @@ enum {
        RT5025_SHDNPRESS_6S,
        RT5025_SHDNPRESS_8S,
        RT5025_SHDNPRESS_10S,
+       RT5025_SHDNPRESS_MAX = RT5025_SHDNPRESS_10S,
 };
 
 enum {
-       RT5025_PGDLY_10MS,
-       RT5025_PGDLY_50MS,
-       RT5025_PGDLY_100MS,
-       RT5025_PGDLY_200MS,
-};
-
-enum {
-       RT5025_SHDNDLY_100MS,
-       RT5025_SHDNDLY_500MS,
-       RT5025_SHDNDLY_1S,
-       RT5025_SHDNDLY_2S,
-};
-
-enum {
-       RT5025_CCCHG_TO_4H,
-       RT5025_CCCHG_TO_6H,
-       RT5025_CCCHG_TO_8H,
-       RT5025_CCCHG_TO_10H,
+       RT5025_VDPM_4V,
+       RT5025_VDPM_4P25V,
+       RT5025_VDPM_4P5V,
+       RT5025_VDPM_DIS,
+       RT5025_VDPM_MAX = RT5025_VDPM_DIS,
 };
 
 enum {
-       RT5025_PRECHG_TO_30M,
-       RT5025_PRECHG_TO_40M,
-       RT5025_PRECHG_TO_50M,
-       RT5025_PRECHG_TO_60M,
-};
-
-enum {
-       RT5025_ICC_0P5A,
-       RT5025_ICC_0P6A,
-       RT5025_ICC_0P7A,
-       RT5025_ICC_0P8A,
-       RT5025_ICC_0P9A,
-       RT5025_ICC_1A,
-       RT5025_ICC_1P1A,
-       RT5025_ICC_1P2A,
-       RT5025_ICC_1P3A,
-       RT5025_ICC_1P4A,
-       RT5025_ICC_1P5A,
-       RT5025_ICC_1P6A,
-       RT5025_ICC_1P7A,
-       RT5025_ICC_1P8A,
-       RT5025_ICC_1P9A,
-       RT5025_ICC_2A,
-       RT5025_ICC_MAX,
-};
-
-enum {
-       RT5025_AICR_100MA,
-       RT5025_AICR_500MA,
-       RT5025_AICR_1A,
-       RT5025_AICR_NOLIMIT,
-};
-
-enum {
-       RT5025_DPM_4V,
-       RT5025_DPM_4P25V,
-       RT5025_DPM_4P5V,
-       RT5025_DPM_DIS,
+       RT5025_IEOC_10P,
+       RT5025_IEOC_20P,
+       RT5025_IEOC_MAX = RT5025_IEOC_20P,
 };
 
 enum {
@@ -134,18 +193,13 @@ enum {
        RT5025_VPREC_2P6V,
        RT5025_VPREC_2P8V,
        RT5025_VPREC_3V,
-       RT5025_VPREC_3V_1,
-       RT5025_VPREC_3V_2,
-};
-
-enum {
-       RT5025_IEOC_10P,
-       RT5025_IEOC_20P,
+       RT5025_VPREC_MAX = RT5025_VPREC_3V,
 };
 
 enum {
        RT5025_IPREC_10P,
        RT5025_IPREC_20P,
+       RT5025_IPREC_MAX = RT5025_IPREC_20P,
 };
 
 enum {
@@ -162,306 +216,58 @@ enum {
        RT5025_MAX_REGULATOR,
 };
 
-struct rt5025_power_data {
-       union {
-               struct {
-                       unsigned char Resv1:1;
-                       unsigned char CHGBC_EN:1;
-                       unsigned char TE:1;
-                       unsigned char Resv2:1;
-                       unsigned char CCCHG_TIMEOUT:2;
-                       unsigned char PRECHG_TIMEOUT:2;
-               }bitfield;
-               unsigned char val;
-       }CHGControl2;
-       union {
-               struct {
-                       unsigned char Resv:2;
-                       unsigned char VOREG:6;
-               }bitfield;
-               unsigned char val;
-       }CHGControl3;
-       union {
-               struct {
-                       unsigned char AICR_CON:1;
-                       unsigned char AICR:2;
-                       unsigned char ICC:4;
-                       unsigned char CHG_RST:1;
-               }bitfield;
-               unsigned char val;
-       }CHGControl4;
-       union {
-               struct {
-                       unsigned char Resv1:4;
-                       unsigned char DPM:2;
-                       unsigned char Resv2:2;
-               }bitfield;
-               unsigned char val;
-       }CHGControl5;
-       union {
-               struct {
-                       unsigned char IPREC:1;
-                       unsigned char IEOC:1;
-                       unsigned char VPREC:3;
-                       unsigned char Resv:3;
-               }bitfield;
-               unsigned char val;
-       }CHGControl6;
-       union {
-               struct {
-                       unsigned char Resv1:4;
-                       unsigned char CHGC_EN:1;
-                       unsigned char CHG_DCDC_MODE:1;
-                       unsigned char BATD_EN:1;
-                       unsigned char Resv2:1;
-               }bitfield;
-               unsigned char val;
-       }CHGControl7;
-};
-
-struct rt5025_gpio_data {
-       unsigned gpio_base;
-       unsigned irq_base;
-};
-
-struct rt5025_misc_data {
-       union {
-               struct {
-                       unsigned char Action:2;
-                       unsigned char Delayed1:2;
-                       unsigned char Delayed2:2;
-                       unsigned char Resv:2;
-               }bitfield;
-               unsigned char val;
-       }RSTCtrl;
-       union {
-               struct {
-                       unsigned char Resv:5;
-                       unsigned char VOFF:3;
-               }bitfield;
-               unsigned char val;
-       }VSYSCtrl;
-       union {
-               struct {
-                       unsigned char PG_DLY:2;
-                       unsigned char SHDN_PRESS:2;
-                       unsigned char LPRESS_TIME:2;
-                       unsigned char START_TIME:2;
-               }bitfield;
-               unsigned char val;
-       }PwrOnCfg;
-       union {
-               struct {
-                       unsigned char Resv:4;
-                       unsigned char SHDN_DLYTIME:2;
-                       unsigned char SHDN_TIMING:1;
-                       unsigned char SHDN_CTRL:1;
-               }bitfield;
-               unsigned char val;
-       }SHDNCtrl;
-       union {
-               struct {
-                       unsigned char Resv:2;
-                       unsigned char OT_ENSHDN:1;
-                       unsigned char PWRON_ENSHDN:1;
-                       unsigned char DCDC3LV_ENSHDN:1;
-                       unsigned char DCDC2LV_ENSHDN:1;
-                       unsigned char DCDC1LV_ENSHDN:1;
-                       unsigned char SYSLV_ENSHDN:1;
-               }bitfield;
-               unsigned char val;
-       }PwrOffCond;
-};
-
-struct rt5025_irq_data {
-       union {
-               struct {
-                       unsigned char BATABS:1;
-                       unsigned char Resv1:2;
-                       unsigned char INUSB_PLUGIN:1;
-                       unsigned char INUSBOVP:1;
-                       unsigned char Resv2:1;
-                       unsigned char INAC_PLUGIN:1;
-                       unsigned char INACOVP:1;
-               }bitfield;
-               unsigned char val;
-       }irq_enable1;
-       union {
-               struct {
-                       unsigned char CHTERMI:1;
-                       unsigned char CHBATOVI:1;
-                       unsigned char CHGOODI_INUSB:1;
-                       unsigned char CHBADI_INUSB:1;
-                       unsigned char CHSLPI_INUSB:1;
-                       unsigned char CHGOODI_INAC:1;
-                       unsigned char CHBADI_INAC:1;
-                       unsigned char CHSLPI_INAC:1;
-               }bitfield;
-               unsigned char val;
-       }irq_enable2;
-       union {
-               struct {
-                       unsigned char TIMEOUT_CC:1;
-                       unsigned char TIMEOUT_PC:1;
-                       unsigned char Resv:3;
-                       unsigned char CHVSREGI:1;
-                       unsigned char CHTREGI:1;
-                       unsigned char CHRCHGI:1;
-               }bitfield;
-               unsigned char val;
-       }irq_enable3;
-       union {
-               struct {
-                       unsigned char SYSLV:1;
-                       unsigned char DCDC4LVHV:1;
-                       unsigned char PWRONLP:1;
-                       unsigned char PWRONSP:1;
-                       unsigned char DCDC3LV:1;
-                       unsigned char DCDC2LV:1;
-                       unsigned char DCDC1LV:1;
-                       unsigned char OT:1;
-               }bitfield;
-               unsigned char val;
-       }irq_enable4;
-       union {
-               struct {
-                       unsigned char Resv:1;
-                       unsigned char GPIO0_IE:1;
-                       unsigned char GPIO1_IE:1;
-                       unsigned char GPIO2_IE:1;
-                       unsigned char RESETB:1;
-                       unsigned char PWRONF:1;
-                       unsigned char PWRONR:1;
-                       unsigned char KPSHDN:1;
-               }bitfield;
-               unsigned char val;
-       }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];
-};
+typedef void (*rt_irq_handler)(void *info, int eventno);
 
-#define CHG_EVENT_INACOVP      (0x80<<16)
-#define CHG_EVENT_INAC_PLUGIN  (0x40<<16)
-#define CHG_EVENT_INUSBOVP     (0x10<<16)
-#define CHG_EVENT_INUSB_PLUGIN (0x08<<16)
-#define CHG_EVENT_BAT_ABS      (0x01<<16)
-
-#define CHG_EVENT_CHSLPI_INAC  (0x80<<8)
-#define CHG_EVENT_CHBADI_INAC  (0x40<<8)
-#define CHG_EVENT_CHGOODI_INAC (0x20<<8)
-#define CHG_EVENT_CHSLPI_INUSB (0x10<<8)
-#define CHG_EVENT_CHBADI_INUSB (0x08<<8)
-#define CHG_EVENT_CHGOODI_INUSB        (0x04<<8)
-#define CHG_EVENT_CHBATOVI     (0x02<<8)
-#define CHG_EVENT_CHTERMI      (0x01<<8)
-
-#define CHG_EVENT_CHRCHGI      (0x80<<0)
-#define CHG_EVENT_CHTREGI      (0x40<<0)
-#define CHG_EVENT_CHVSREGI     (0x20<<0)
-#define CHG_EVENT_TIMEOUTPC    (0x02<<0)
-#define CHG_EVENT_TIMEOUTCC    (0x01<<0)
-
-#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_CHTERMI | CHG_EVENT_CHRCHGI)
-
-#define PWR_EVENT_OTIQ         (0x80<<8)
-#define PWR_EVENT_DCDC1LV      (0x40<<8)
-#define PWR_EVENT_DCDC2LV      (0x20<<8)
-#define PWR_EVENT_DCDC3LV      (0x10<<8)
-#define PWR_EVENT_PWRONSP      (0x08<<8)
-#define PWR_EVENT_PWRONLP      (0x04<<8)
-#define PWR_EVENT_DCDC4LVHV    (0x02<<8)
-#define PWR_EVENT_SYSLV                (0x01<<8)
-
-#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_GPIO2IE      (0x08<<0)
-#define PWR_EVENT_GPIO1IE      (0x04<<0)
-#define PWR_EVENT_GPIO0IE      (0x02<<0)
-
-struct rt5025_event_callback {
-       #if 1
-       void (*charger_event_callback)(uint32_t detected);
-       void (*power_event_callkback)(uint32_t detected);
-       #else
-       void (*over_temperature_callback)(uint8_t detected);
-       void (*charging_complete_callback)(void);
-       void (*over_voltage_callback)(uint8_t detected);
-       void (*under_voltage_callback)(uint8_t detected);
-       void (*charge_fault_callback)(uint8_t detected);
-       void (*charge_warning_callback)(uint8_t detected);
-       #endif
+#define RT5025_DCDCRAMP_MAX    0x03
+struct rt5025_regulator_ramp {
+       unsigned char ramp_sel:2;
 };
 
-struct rt5025_power_info {
+struct rt5025_charger_info {
        struct i2c_client       *i2c;
        struct device           *dev;
-       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;
-       int chg_term;
-       int otg_en;
-       unsigned                ac_online:1;
-       unsigned                usb_online:1;
-       unsigned                chg_stat:3;
-};
-
-struct rt5025_swjeita_info {
-       struct i2c_client *i2c;
-       struct rt5025_chip *chip;
-       struct delayed_work thermal_reg_work;
-       int *temp;
-       u8 *temp_scalar;
-       int (*temp_cc)[5];
-       int (*temp_cv)[5];
-       int dec_current;
-       int cur_section;
-       int cur_therm_region;
-       int cur_cable;
-       int cur_temp;
-       int cur_inttemp;
-       int init_once;
-       int suspend;
+       struct power_supply     psy;
+#ifdef CONFIG_HAS_EARLYSUSPEND
+       struct early_suspend early_suspend;
+#endif /* CONFIG_HAS_EARLYSUSPEND */
+       struct delayed_work tempmon_work;
+       int temp[4];
+       u32 temp_scalar[8];
+       unsigned int te_en:1;
+       unsigned int online:1;
+       unsigned int batabs:1;
+       unsigned int battemp_region:3;
+       unsigned int inttemp_region:2;
+       unsigned int otg_en:1;
+       unsigned int init_once:1;
+       unsigned int suspend:1;
+       unsigned int screenon_adjust:1;
+       unsigned int screen_on:1;
+       int chg_status;
+       int charger_cable;
+       int chg_volt;
+       int acchg_icc;
+       int usbtachg_icc;
+       int usbchg_icc;
+       int screenon_icc;
 };
 
 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;
        struct wake_lock status_wake_lock;
-//#if RT5025_TEST_WAKE_LOCK
-       struct wake_lock test_wake_lock;
-//#endif
+       struct wake_lock smooth0_wake_lock;
+       struct wake_lock smooth100_wake_lock;
+       struct wake_lock full_battery_wake_lock;
+       /*#if RT5025_TEST_WAKE_LOCK
+       //      struct wake_lock test_wake_lock;
+       //#endif*/
+       struct mutex status_change_lock;
        struct alarm wakeup_alarm;
-       
+
        bool temp_range_0_5;
        bool temp_range_5_10;
        bool temp_range_10_15;
@@ -471,7 +277,7 @@ struct rt5025_battery_info {
        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;
@@ -481,159 +287,183 @@ struct rt5025_battery_info {
        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 internal temperature */
-  s16 int_temp;
-  /* 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;
+       /*      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 internal temperature */
+       s16 int_temp;
+       /* 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;
+       u8 batt_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;
-  u32 empty_edv;
-  u8  edv_region;
-
-  bool init_once;
-  bool device_suspend;
-  bool last_suspend;
-  bool last_tp_flag;
-  u32 cal_fcc;
-  u8 test_temp;
+
+       /* remain capacity */
+       u32 rm;
+       /* SOC permille  */
+       u16 permille;
+       /* full capccity */
+       u16 fcc_aging;
+       u16 fcc;
+       u16     dc;
+       s16 tempcmp;
+
+       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;
+       u32 empty_edv;
+       u8  edv_region;
+       u32  soc1_lock_cnt;
+       u32  soc99_lock_cnt;
+
+       bool init_once;
+       bool device_suspend;
+       bool last_suspend;
+       bool last_tp_flag;
+       bool fcc_update_flag;
+       u32 cal_fcc;
+       u8 test_temp;
+       u8  last_tp;
+       u32 cal_eoc_fcc;
+       u32 cal_soc_offset;
 };
 
-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_charger_data {
+       int *temp;
+       u32 *temp_scalar;
+       int chg_volt;
+       int acchg_icc;
+       int usbtachg_icc;
+       int usbchg_icc;
+       int screenon_icc;
+       unsigned int ieoc:1;
+       unsigned int vdpm:2;
+       unsigned int te_en:1;
+       unsigned int vprec:3;
+       unsigned int iprec:1;
+       unsigned int screenon_adjust:1;
 };
 
+struct rt5025_gpio_data {
+       int ngpio;
+};
+
+struct rt5025_misc_data {
+       unsigned char vsyslv:3;
+       unsigned char shdnlpress_time:2;
+       unsigned char startlpress_time:2;
+       unsigned char vsyslv_enshdn:1;
+};
+
+struct rt5025_irq_data {
+       int irq_gpio;
+};
+
+struct rt5025_chip;
 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;
+       struct regulator_init_data *regulator[RT5025_MAX_REGULATOR];
+       struct rt5025_charger_data *chg_pdata;
+       struct rt5025_gpio_data *gpio_pdata;
+       struct rt5025_misc_data *misc_pdata;
+       struct rt5025_irq_data *irq_pdata;
        int (*pre_init)(struct rt5025_chip *rt5025_chip);
        /** Called after subdevices are set up */
        int (*post_init)(void);
-       int (*set_otg_enable)(int);
-       int intr_pin;
 };
 
-#ifdef CONFIG_MFD_RT5025_MISC
-extern void rt5025_power_off(void);
-extern int rt5025_cable_exist(void);
-#endif /* CONFIG_MFD_RT5025_MISC */
-
-#ifdef CONFIG_POWER_RT5025
-extern int rt5025_charger_reset_and_reinit(struct rt5025_power_info *);
-extern int rt5025_ext_set_charging_buck(int);
-extern int rt5025_set_charging_buck(struct i2c_client *, int);
-extern int rt5025_set_charging_current_switch(struct i2c_client *, int);
-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 */
+struct rt5025_misc_info {
+       struct i2c_client *i2c;
+       struct device *dev;
+};
+
+struct rt5025_chip {
+       struct i2c_client *i2c;
+       struct device *dev;
+       struct rt5025_charger_info *charger_info;
+       struct rt5025_battery_info *battery_info;
+       struct rt5025_misc_info *misc_info;
+       struct mutex io_lock;
+       int suspend;
+};
+
+#ifdef CONFIG_CHARGER_RT5025
+void rt5025_charger_irq_handler(struct rt5025_charger_info *ci, unsigned int event);
+#endif /* #ifdef CONFIG_CHARGER_RT5025 */
+#ifdef CONFIG_MISC_RT5025
+void rt5025_misc_irq_handler(struct rt5025_misc_info *mi, unsigned int event);
+#endif /* #ifdef CONFIG_MISC_RT5025 */
+#ifdef CONFIG_BATTERY_RT5025
+void rt5025_gauge_irq_handler(struct rt5025_battery_info *bi, unsigned int event);
+#endif /* #ifdef CONFIG_BATTERY_RT5025 */
 
 extern int rt5025_reg_block_read(struct i2c_client *, int, int, void *);
 extern int rt5025_reg_block_write(struct i2c_client *, int, int, void *);
@@ -648,9 +478,9 @@ extern int rt5025_core_deinit(struct rt5025_chip *);
 
 #ifdef CONFIG_MFD_RT_SHOW_INFO
 #define RTINFO(format, args...) \
-       printk(KERN_INFO "%s:%s() line-%d: " format, RT5025_DEVICE_NAME,__FUNCTION__,__LINE__, ##args)
+       printk(KERN_INFO "%s:%s() line-%d: " format, RT5025_DEV_NAME, __FUNCTION__, __LINE__, ##args)
 #else
-#define RTINFO(format,args...)
+#define RTINFO(format, args...)
 #endif /* CONFIG_MFD_RT_SHOW_INFO */
 
 #endif /* __LINUX_MFD_RT5025_H */
index 352be48c8bb6e72b5ad85db114f80fea2dab0036..ae5eb522627ca424d9967345a066dc976c637763 100755 (executable)
@@ -1,26 +1,24 @@
-battery_graph_prop rt5025_battery_param1[] =
-{
+battery_graph_prop rt5025_battery_param1[] = {
   {4190, 1000},
-  {4120, 980},
-  {4037, 890},
-  {3970, 800},
-  {3914, 710},
-  {3835, 580},
-  {3796, 490},
-  {3773, 400},
-  {3736, 240},
-  {3697, 140},
-  {3665, 70},
-  {3651, 50},
-  {3545, 20},
-  {3400, 0},   
+  {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,14},
+battery_graph_prop rt5025_battery_param2[] = {
+  {450, 30},
   {250, 0},
-  {50,-78},
-  {50,  10},
-  {3400, 3671},
+  {50, -90},
+  {50, 10},
+  {3400, 6900},
 };
diff --git a/include/linux/power/rt-power.h b/include/linux/power/rt-power.h
new file mode 100755 (executable)
index 0000000..7c5b64a
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  include/linux/power/rt5025/rt-power.h
+ *  Include header file for Richtek RT5025 Core charger Driver
+ *
+ *  Copyright (C) 2014 Richtek Technology Corp.
+ *  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; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#ifndef __LINUX_RT_POWER_H
+#define __LINUX_RT_POWER_H
+
+#define RT_AC_NAME     "rt-ac"
+#define RT_USB_NAME    "rt-usb"
+
+struct rt_power_data {
+       int chg_volt;
+       int acchg_icc;
+       int usbtachg_icc;
+       int usbchg_icc;
+};
+#endif /* #ifndef __LINUX_RT_POWER_H */
+
old mode 100644 (file)
new mode 100755 (executable)
index b957745..a1f1add
@@ -1,13 +1,14 @@
 /*
- *  include/linux/power/rt5025-battery.h
+ *  include/linux/power/rt5025/rt5025-battery.h
  *  Include header file for Richtek RT5025 battery Driver
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2013 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #ifndef __LINUX_RT5025_BATTERY_H
 #undef ROCKCHIP_BATTERY_6900MAH
 #undef ROCKCHIP_BATTERY_4000MAH
 
-#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  0x5A
-#define RT5025_REG_INT_TEMPERATUE_LSB  0x5B
-#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 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  0x5A
+#define RT5025_REG_INT_TEMPERATUE_LSB  0x5B
+#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 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 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
-
-u16 crctab16[256] =
-{
-                0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 
-                0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 
-                0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 
-                0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 
-                0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 
-                0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 
-                0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 
-                0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 
-                0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 
-                0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 
-                0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 
-                0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 
-                0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 
-                0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 
-                0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 
-                0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 
-                0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 
-                0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 
-                0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 
-                0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 
-                0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 
-                0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 
-                0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 
-                0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 
-                0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 
-                0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 
-                0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 
-                0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 
-                0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 
-                0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 
-                0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 
-                0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
-};
+/*#define SLEEP_CURRENT 3 //mA*/
 
 typedef enum{
        CHG,
        DCHG
-}operation_mode;
+} operation_mode;
 
 typedef struct{
        int x;
        int y;
-}battery_graph_prop;
+} battery_graph_prop;
 
 typedef enum {
        MAXTEMP,
@@ -146,7 +111,7 @@ typedef enum {
        TEMP_RLS,
        VOLT_RLS,
        LAST_TYPE,
-}alert_type;
+} alert_type;
 
 #if defined(ROCKCHIP_BATTERY_6900MAH)
 #include <linux/power/rockchip-6900ma-bat.h>
@@ -156,6 +121,6 @@ typedef enum {
 #include <linux/power/rockchip-general-bat.h>
 #endif
 
-#define VALRTMIN2_VALUE (rt5025_battery_param2[4].x * 100 / IRQ_THRES_UNIT + 1) //EDV0 voltage
+#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-charger.h b/include/linux/power/rt5025-charger.h
new file mode 100755 (executable)
index 0000000..85f83bc
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ *  include/linux/power/rt5025/rt5025-charger.h
+ *  Include header file for Richtek RT5025 Core charger Driver
+ *
+ *  Copyright (C) 2014 Richtek Technology Corp.
+ *  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; either version 2
+ * of the License, or (at your option) any later version.
+ */
+
+#ifndef __LINUX_RT5025_CHARGER_H
+#define __LINUX_RT5025_CHARGER_H
+
+enum {
+       CHGEVENT_TIMEOUT_CC,
+       CHGEVENT_TIMEOUT_PC,
+       CHGEVENT_CHVSREGI = 5,
+       CHGEVENT_CHTREGI,
+       CHGEVENT_CHRCHGI,
+       CHGEVENT_CHTERMI,
+       CHGEVENT_CHBATOVI,
+       CHGEVENT_CHGOODI_INUSB,
+       CHGEVENT_CHBADI_INUSB,
+       CHGEVENT_CHSLPI_INUSB,
+       CHGEVENT_CHGOODI_INAC,
+       CHGEVENT_CHBADI_INAC,
+       CHGEVENT_CHSLPI_INAC,
+       CHGEVENT_BATABS,
+       CHGEVENT_INUSB_PLUGIN = 19,
+       CHGEVENT_INUSBOVP,
+       CHGEVENT_INAC_PLUGIN = 22,
+       CHGEVENT_INACOVP,
+       /*append TALRT IRQ*/
+       CHGEVENT_TALRTMIN = 28,
+       CHGEVENT_TALRTMAX = 29,
+       CHGEVENT_MAX,
+};
+
+enum {
+       RT5025_BATTEMP_COLD,
+       RT5025_BATTEMP_COOL,
+       RT5025_BATTEMP_NORMAL,
+       RT5025_BATTEMP_WARM,
+       RT5025_BATTEMP_HOT,
+       RT5025_BATTEMP_MAX,
+};
+
+enum {
+       RT5025_INTTEMP_NORMAL,
+       RT5025_INTTEMP_WARM,
+       RT5025_INTTEMP_HOT,
+       RT5025_INTTEMP_MAX,
+};
+
+#define RT5025_CHGIPREC_MASK   0x01
+#define RT5025_CHGIPREC_SHFT   0
+#define RT5025_CHGIEOC_MASK    0x02
+#define RT5025_CHGIEOC_SHFT    1
+#define RT5025_CHGVPREC_MASK   0x1C
+#define RT5025_CHGVPREC_SHFT   2
+#define RT5025_CHGVDPM_MASK    0x30
+#define RT5025_CHGVDPM_SHFT    4
+
+#define RT5025_CHGCEN_MASK     0x10
+#define RT5025_CHGAICR_MASK    0x06
+#define RT5025_CHGAICR_SHFT    1
+#define RT5025_CHGICC_MASK     0x78
+#define RT5025_CHGICC_SHFT     3
+#define RT5025_CHGCV_MASK      0xFC
+#define RT5025_CHGCV_SHFT      2
+#define RT5025_CHGTEEN_MASK    0x04
+#define RT5025_BATDEN_MASK     0x40
+#define RT5025_VBUSHZ_MASK     0x01
+#define RT5025_CHGBCEN_MASK    0x02
+#define RT5025_CHRCHGI_MASK    0x80
+#define RT5025_CHTERMI_MASK    0x01
+#define RT5025_ACUSABLE_MASK   0x02
+#define RT5025_USBUSABLE_MASK  0x01
+
+#define RT5025_TALRTMX_MASK    0x20
+#define RT5025_TALRTMN_MASK    0x10
+
+#endif /* #ifndef __LINUX_RT5025_POWER_H */
old mode 100644 (file)
new mode 100755 (executable)
index f946783..154b8c1
@@ -2,88 +2,75 @@
  *  include/linux/regulator/rt5025-regulator.h
  *  Include header file to Richtek RT5025 Regulator driver
  *
- *  Copyright (C) 2013 Richtek Electronics
+ *  Copyright (C) 2013 Richtek Technology Corp.
  *  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.
+ * published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
  */
 
 #ifndef __LINUX_RT5025_REGULATOR_H
 #define __LINUX_RT5025_REGULATOR_H
 
-#define RT5025_REG_DCDCCTRL1 0x08
-#define RT5025_REG_DCDCCTRL2 0x09
-#define RT5025_REG_DCDCCTRL3 0x0A
-#define RT5025_REG_DCDCCTRL4 0x0B
-#define RT5025_REG_LDOCTRL1  0x0D
-#define RT5025_REG_LDOCTRL2  0x0E
-#define RT5025_REG_LDOCTRL3  0x0F
-#define RT5025_REG_LDOCTRL4  0x10
-#define RT5025_REG_LDOCTRL5  0x11
-#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_DCDCCTL1
+#define RT5025_DCDCVOUT2       RT5025_REG_DCDCCTL2
+#define RT5025_DCDCVOUT3       RT5025_REG_DCDCCTL3
+#define RT5025_DCDCVOUT4       RT5025_REG_VRCCTL
+#define RT5025_LDOVOUT1        RT5025_REG_LDOCTL1
+#define RT5025_LDOVOUT2        RT5025_REG_LDOCTL2
+#define RT5025_LDOVOUT3        RT5025_REG_LDOCTL3
+#define RT5025_LDOVOUT4        RT5025_REG_LDOCTL4
+#define RT5025_LDOVOUT5        RT5025_REG_LDOCTL5
+#define RT5025_LDOVOUT6        RT5025_REG_LDOCTL6
 
-#define RT5025_DCDCVOUT1     RT5025_REG_DCDCCTRL1
-#define RT5025_DCDCVOUT2     RT5025_REG_DCDCCTRL2
-#define RT5025_DCDCVOUT3     RT5025_REG_DCDCCTRL3
-#define RT5025_DCDCVOUT4     RT5025_REG_DCDCCTRL4
-#define RT5025_LDOVOUT1      RT5025_REG_LDOCTRL1
-#define RT5025_LDOVOUT2      RT5025_REG_LDOCTRL2
-#define RT5025_LDOVOUT3      RT5025_REG_LDOCTRL3
-#define RT5025_LDOVOUT4      RT5025_REG_LDOCTRL4
-#define RT5025_LDOVOUT5      RT5025_REG_LDOCTRL5
-#define RT5025_LDOVOUT6      RT5025_REG_LDOCTRL6
+#define RT5025_DCDCVOUT_SHIFT1 2
+#define RT5025_DCDCVOUT_SHIFT2 1
+#define RT5025_DCDCVOUT_SHIFT3 2
+#define RT5025_DCDCVOUT_SHIFT4 0
+#define RT5025_LDOVOUT_SHIFT1  0
+#define RT5025_LDOVOUT_SHIFT2  0
+#define RT5025_LDOVOUT_SHIFT3  3
+#define RT5025_LDOVOUT_SHIFT4  3
+#define RT5025_LDOVOUT_SHIFT5  3
+#define RT5025_LDOVOUT_SHIFT6  3
 
-#define RT5025_DCDCVOUT_SHIFT1    2
-#define RT5025_DCDCVOUT_SHIFT2    1
-#define RT5025_DCDCVOUT_SHIFT3    2
-#define RT5025_DCDCVOUT_SHIFT4   0
-#define RT5025_LDOVOUT_SHIFT1     0
-#define RT5025_LDOVOUT_SHIFT2     0
-#define RT5025_LDOVOUT_SHIFT3     3
-#define RT5025_LDOVOUT_SHIFT4     3
-#define RT5025_LDOVOUT_SHIFT5     3
-#define RT5025_LDOVOUT_SHIFT6     3
+#define RT5025_DCDCVOUT_MASK1  0xFC
+#define RT5025_DCDCVOUT_MASK2  0xFE
+#define RT5025_DCDCVOUT_MASK3  0xFC
+#define RT5025_DCDCVOUT_MASK4  0x0F
+#define RT5025_LDOVOUT_MASK1   0x7F
+#define RT5025_LDOVOUT_MASK2   0x7F
+#define RT5025_LDOVOUT_MASK3   0xF8
+#define RT5025_LDOVOUT_MASK4   0xF8
+#define RT5025_LDOVOUT_MASK5   0xF8
+#define RT5025_LDOVOUT_MASK6   0xF8
 
-#define RT5025_DCDCVOUT_MASK1     0xFC
-#define RT5025_DCDCVOUT_MASK2     0xFE
-#define RT5025_DCDCVOUT_MASK3     0xFC
-#define RT5025_DCDCVOUT_MASK4    0x0F
-#define RT5025_LDOVOUT_MASK1      0x7F
-#define RT5025_LDOVOUT_MASK2      0x7F
-#define RT5025_LDOVOUT_MASK3      0xF8
-#define RT5025_LDOVOUT_MASK4      0xF8
-#define RT5025_LDOVOUT_MASK5      0xF8
-#define RT5025_LDOVOUT_MASK6      0xF8
+#define RT5025_DCDCEN_MASK1    0x01
+#define RT5025_DCDCEN_MASK2    0x02
+#define RT5025_DCDCEN_MASK3    0x04
+#define RT5025_DCDCEN_MASK4    0x08
+#define RT5025_LDOEN_MASK1     0x01
+#define RT5025_LDOEN_MASK2     0x02
+#define RT5025_LDOEN_MASK3     0x04
+#define RT5025_LDOEN_MASK4     0x08
+#define RT5025_LDOEN_MASK5     0x10
+#define RT5025_LDOEN_MASK6     0x20
 
-#define RT5025_DCDC_OUTPUT_EN     RT5025_REG_DCDCEN
-#define RT5025_LDO_OUTPUT_EN      RT5025_REG_LDOEN
+#define RT5025_DCDCMODE_REG1   RT5025_REG_VRCCTL
+#define RT5025_DCDCMODE_REG2   RT5025_REG_VRCCTL
+#define RT5025_DCDCMODE_REG3   RT5025_REG_VRCCTL
+#define RT5025_DCDCMODE_REG4   0
 
-#define RT5025_DCDCEN_MASK1       0x01
-#define RT5025_DCDCEN_MASK2       0x02
-#define RT5025_DCDCEN_MASK3       0x04
-#define RT5025_DCDCEN_MASK4      0x08
-#define RT5025_LDOEN_MASK1        0x01
-#define RT5025_LDOEN_MASK2        0x02
-#define RT5025_LDOEN_MASK3        0x04
-#define RT5025_LDOEN_MASK4        0x08
-#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_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
+#define RT5025_DCDCRAMP_MASK1  0x03
+#define RT5025_DCDCRAMP_MASK2  0x01
+#define RT5025_DCDCRAMP_MASK3  0x03
+#define RT5025_DCDCRAMP_MASK4  0x00
 
 #endif  /* __LINUX_RT5025_REGULATOR_H */