[1 of 1][10277828]fuel gauge bringup

 ###%%%comment:[1 of 1]fuel gauge bringup
 ###%%%bug number:10277828
 ###%%%product name:n10
 ###%%%root cause:Coding
 ###%%%Bug category:T2M
 ###%%%regression response:NO
 ###%%%regression comments:
 ###%%%Module_Impact:kernel
 ###%%%Test_Suggestion:test bq27541 gauge
 ###%%%Solution:bq27541 hdq driver
 ###%%%Test_Report:hdq read/write fail
 ###%%%VAL Can Test:No

Change-Id: I896400160b1fc527a9efc6bc84994d055db71fd2
diff --git a/arch/arm64/configs/vendor/n10-perf_defconfig b/arch/arm64/configs/vendor/n10-perf_defconfig
index 58e095e..b5ec5b2 100644
--- a/arch/arm64/configs/vendor/n10-perf_defconfig
+++ b/arch/arm64/configs/vendor/n10-perf_defconfig
@@ -719,4 +719,5 @@
 CONFIG_TCT_CHG_AUTOTEST=y
 CONFIG_TCT_PM7250_COMMON=y
 CONFIG_USB_PD_LOG_LVL=1
+CONFIG_BATTERY_BQ27541_HDQ=y
 
diff --git a/arch/arm64/configs/vendor/n10_defconfig b/arch/arm64/configs/vendor/n10_defconfig
index 5338249..1e6b15d 100644
--- a/arch/arm64/configs/vendor/n10_defconfig
+++ b/arch/arm64/configs/vendor/n10_defconfig
@@ -787,3 +787,4 @@
 CONFIG_TCT_CHG_AUTOTEST=y
 CONFIG_TCT_PM7250_COMMON=y
 CONFIG_USB_PD_LOG_LVL=1
+CONFIG_BATTERY_BQ27541_HDQ=y
\ No newline at end of file
diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
index bbccf3f..ba5867c 100644
--- a/drivers/power/supply/Kconfig
+++ b/drivers/power/supply/Kconfig
@@ -645,6 +645,12 @@
 	  what is connected to USB PD ports from the EC and converts
 	  that into power_supply properties.
 
+config BATTERY_BQ27541_HDQ
+       tristate "BQ27541 battery driver"
+       depends on OF
+       help
+         Say Y here to enable support for batteries with BQ27541 (HDQ) chips.
+
 source "drivers/power/supply/qcom/Kconfig"
 
 endif # POWER_SUPPLY
diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
index 31305eb..6bd6f36 100644
--- a/drivers/power/supply/Makefile
+++ b/drivers/power/supply/Makefile
@@ -86,3 +86,4 @@
 obj-$(CONFIG_AXP288_CHARGER)	+= axp288_charger.o
 obj-$(CONFIG_CHARGER_CROS_USBPD)	+= cros_usbpd-charger.o
 obj-$(CONFIG_ARCH_QCOM)		+= qcom/
+obj-$(CONFIG_BATTERY_BQ27541_HDQ)   += bq27541_fuelgauger_hdq.o
diff --git a/drivers/power/supply/bq27541-hdq-gpio.h b/drivers/power/supply/bq27541-hdq-gpio.h
new file mode 100644
index 0000000..58ef159
--- /dev/null
+++ b/drivers/power/supply/bq27541-hdq-gpio.h
@@ -0,0 +1,146 @@
+/*
+ * hdq-gpio interface to platform code
+ *
+ * Copyright (C) 2014 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ */
+#ifndef _LINUX_BQ27541_HDQ_GPIO_H
+#define _LINUX_BQ27541_HDQ_GPIO_H
+	
+#define DRIVER_VERSION			"1.1.0"
+	/* Bq27541 standard/extended data commands */
+#define bq27541CMD_CNTL_LSB  0x00
+#define bq27541CMD_CNTL_MSB  0x01
+#define bq27541CMD_AR_LSB	 0x02
+#define bq27541CMD_AR_MSB	 0x03
+#define bq27541CMD_ARTTE_LSB 0x04
+#define bq27541CMD_ARTTE_MSB 0x05
+#define bq27541CMD_TEMP_LSB  0x06
+#define bq27541CMD_TEMP_MSB  0x07
+#define bq27541CMD_VOLT_LSB  0x08
+#define bq27541CMD_VOLT_MSB  0x09
+#define bq27541CMD_FLAGS_LSB 0x0A
+#define bq27541CMD_FLAGS_MSB 0x0B
+#define bq27541CMD_NAC_LSB	 0x0C
+#define bq27541CMD_NAC_MSB	 0x0D
+#define bq27541CMD_FAC_LSB	 0x0E
+#define bq27541CMD_FAC_MSB	 0x0F
+#define bq27541CMD_RM_LSB	 0x10
+#define bq27541CMD_RM_MSB	 0x11
+#define bq27541CMD_FCC_LSB	 0x12
+#define bq27541CMD_FCC_MSB	 0x13
+#define bq27541CMD_AI_LSB	 0x14
+#define bq27541CMD_AI_MSB	 0x15
+#define bq27541CMD_TTE_LSB	 0x16
+#define bq27541CMD_TTE_MSB	 0x17
+#define bq27541CMD_TTF_LSB	 0x18
+#define bq27541CMD_TTF_MSB	 0x19
+#define bq27541CMD_SI_LSB	 0x1A
+#define bq27541CMD_SI_MSB	 0x1B
+#define bq27541CMD_STTE_LSB  0x1C
+#define bq27541CMD_STTE_MSB  0x1D
+#define bq27541CMD_MLI_LSB	 0x1E
+#define bq27541CMD_MLI_MSB	 0x1F
+#define bq27541CMD_MLTTE_LSB 0x20
+#define bq27541CMD_MLTTE_MSB 0x21
+#define bq27541CMD_AE_LSB	 0x22
+#define bq27541CMD_AE_MSB	 0x23
+#define bq27541CMD_AP_LSB	 0x24
+#define bq27541CMD_AP_MSB	 0x25
+#define bq27541CMD_TTECP_LSB 0x26
+#define bq27541CMD_TTECP_MSB 0x27
+#define bq27541CMD_RSVD_LSB  0x28
+#define bq27541CMD_RSVD_MSB  0x29
+#define bq27541CMD_CC_LSB	 0x2A
+#define bq27541CMD_CC_MSB	 0x2B
+#define bq27541CMD_SOC_LSB	 0x2C
+#define bq27541CMD_SOC_MSB	 0x2D
+#define bq27541CMD_SOH_LSB	 0x2E
+#define bq27541CMD_DCAP_LSB  0x3C
+#define bq27541CMD_DCAP_MSB  0x3D
+#define bq27541CMD_DFCLS	 0x3E
+#define bq27541CMD_DFBLK	 0x3F
+#define bq27541CMD_ADF		 0x40
+#define bq27541CMD_ACKSDFD	 0x54
+#define bq27541CMD_DFDCKS	 0x60
+#define bq27541CMD_DFDCNTL	 0x61
+#define bq27541CMD_DNAMELEN  0x62
+#define bq27541CMD_DNAME	 0x63
+	
+#define BQ27541_FLAG_DSC		BIT(0)
+#define BQ27541_FLAG_SOCF		BIT(1) /* State-of-Charge threshold final */
+#define BQ27541_FLAG_SOC1		BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27541_FLAG_FC 		BIT(9)
+#define BQ27541_FLAG_OTD		BIT(14)
+#define BQ27541_FLAG_OTC		BIT(15)
+	
+#define BQ27541_CS_SS			BIT(13)
+#define BQ27541_CS_DLOGEN		BIT(15)
+
+/* Control subcommands */
+#define BQ27541_SUBCMD_CTNL_STATUS  0x0000
+#define BQ27541_SUBCMD_DEVCIE_TYPE  0x0001
+#define BQ27541_SUBCMD_FW_VER       0x0002
+#define BQ27541_SUBCMD_HW_VER       0x0003
+#define BQ27541_SUBCMD_DF_CSUM      0x0004
+#define BQ27541_SUBCMD_PREV_MACW    0x0007
+#define BQ27541_SUBCMD_CHEM_ID      0x0008
+#define BQ27541_SUBCMD_BD_OFFSET    0x0009
+#define BQ27541_SUBCMD_INT_OFFSET   0x000a
+#define BQ27541_SUBCMD_CC_VER       0x000b
+#define BQ27541_SUBCMD_OCV          0x000c
+#define BQ27541_SUBCMD_BAT_INS      0x000d
+#define BQ27541_SUBCMD_BAT_REM      0x000e
+#define BQ27541_SUBCMD_SET_HIB      0x0011
+#define BQ27541_SUBCMD_CLR_HIB      0x0012
+#define BQ27541_SUBCMD_SET_SLP      0x0013
+#define BQ27541_SUBCMD_CLR_SLP      0x0014
+#define BQ27541_SUBCMD_FCT_RES      0x0015
+#define BQ27541_SUBCMD_ENABLE_DLOG  0x0018
+#define BQ27541_SUBCMD_DISABLE_DLOG 0x0019
+#define BQ27541_SUBCMD_SEALED       0x0020
+#define BQ27541_SUBCMD_ENABLE_IT    0x0021
+#define BQ27541_SUBCMD_DISABLE_IT   0x0023
+#define BQ27541_SUBCMD_CAL_MODE     0x0040
+#define BQ27541_SUBCMD_RESET        0x0041
+
+#define BQ27542_DEVICE_ID 0x542
+
+#include <linux/power_supply.h>
+
+static enum power_supply_property bq27541_battery_props[] = {
+	//POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_PRESENT, // jason.kim 2015.10.15
+	POWER_SUPPLY_PROP_VOLTAGE_NOW,
+	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+	POWER_SUPPLY_PROP_TEMP,
+	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
+	//POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	//POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	//POWER_SUPPLY_PROP_CYCLE_COUNT,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	//POWER_SUPPLY_PROP_POWER_AVG,
+	POWER_SUPPLY_PROP_HEALTH,
+	POWER_SUPPLY_PROP_TEMP,
+};
+
+#if 0
+int bq27541_battery_get_property(struct power_supply *psy,
+					enum power_supply_property psp,
+					union power_supply_propval *val);
+
+void bq27541_external_power_changed(struct power_supply *psy);
+#endif
+
+
+#endif /* _LINUX_HDQ_GPIO_H */
+
diff --git a/drivers/power/supply/bq27541_fuelgauger_hdq.c b/drivers/power/supply/bq27541_fuelgauger_hdq.c
new file mode 100644
index 0000000..c0d472c
--- /dev/null
+++ b/drivers/power/supply/bq27541_fuelgauger_hdq.c
@@ -0,0 +1,2700 @@
+/* Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
+ * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
+ *
+ * Copyright (c) 2011, 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.
+ */
+// jason.kim 2015.11.12 update driver
+//   Fix failure often to read from battery through HDQ
+//   Tidy up codes that update and check parameters of battery
+//   Add reporting current
+//   Add writing to battery through HDQ
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include "bq27541-hdq-gpio.h"
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/param.h>
+#include <linux/jiffies.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/idr.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+//#include <linux/mfd/pmic8058.h>
+//#include <linux/regulator/pmic8058-regulator.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/machine.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+//#include <emkit/emkit.h>
+#include <linux/spinlock.h>
+//#include <linux/msm-charger.h>
+#include <linux/sort.h>
+//#define ZXZ_BQ27541
+ #define DEBUG_BQ
+ //#define DEBUG_HDQ
+ //#define DEBUG_UPDATE_VALUE
+ //#define DEBUG_INIT_VALUE
+#define NOT_USE_HDQ_TEMPERATURE  // modefied by robin.cho. charger and HDQ has a gap for temperature. For remove it, i get temperature from charger.
+
+
+#define USE_REMAP_TABLE // jason.kim 2015.11.23 use remap table
+// #define USE_SW_TUNE  // jason.kim 2015.11.27 use increase 100%, 0% ranges
+#define USE_SERIAL_32_BYTES // jason.kim 2015.12.08 use only 12 bytes for the serial number
+#ifdef USE_SERIAL_32_BYTES
+
+typedef struct _serial_number
+{
+	unsigned char length_SN;
+	char SN[13];
+	unsigned char pad1;
+	unsigned char length_ModelName;
+	char ModelName[10];
+	unsigned char pad2;
+	unsigned char length_MF_date;
+	char MF_date[4];	
+}PM85_SERIAL;
+#endif
+//+ jason.kim 2015.11.24 dump registers
+#define BQ27541_REG_CNTL		0x00 /* Control Register */
+#define BQ27541_REG_AR		    0x02 /* At rate */
+#define BQ27541_REG_UFSOC		0x04 /* Unfiltered SOC */
+#define BQ27541_REG_TEMP		0x06 /* Temperature */
+#define BQ27541_REG_VOLT		0x08 /* Voltage */
+#define BQ27541_REG_FLAGS		0x0A
+#define BQ27541_REG_NAC		    0x0C /* Nominal available capacity */
+#define BQ27541_REG_FAC		    0x0E /* Full available capacity */
+#define BQ27541_REG_RM		    0x10 /* Remaining available capacity */
+#define BQ27541_REG_FCC		    0x12 /* Full charge capacity */
+#define BQ27541_REG_AI		    0x14 /* Average current */
+#define BQ27541_REG_TTE		    0x16 /* Time to empty */
+#define BQ27541_REG_FFCC		0x18 /* Filtered FCC */
+#define BQ27541_REG_SI		    0x1A /* Standby current */
+#define BQ27541_REG_UFFCC       0x1C /* Unfiltered FCC */
+#define BQ27541_REG_MLI         0x1E /* Max load current */
+#define BQ27541_REG_UFRM        0x20 /* Unfiltered RM */
+#define BQ27541_REG_FRM         0x22 /* Filtered RM */
+#define BQ27541_REG_AP          0x24 /* Average power */
+
+#define BQ27541_REG_INTTEMP     0x28 /* Internal temperature */
+#define BQ27541_REG_CC          0x2A /* Cycle count */
+#define BQ27541_REG_SOC         0x2C /* State of charge */
+#define BQ27541_REG_SOH         0x2E /* State of health */
+
+#define BQ27541_REG_PCHG        0x34 /* Passed charge */
+#define BQ27541_REG_DOD0        0x36 /* Depth of discharge during the most recent OCV reading */
+#define BQ27541_REG_SDSG        0x38 /* Self-discharge current */
+//- jason.kim 2015.11.24 dump registers
+
+//+ jason.kim 2015.12.07 serial number
+#define BQ27541_REG_DFCLS       0x3E /* DataFlashClass */
+#define BQ27541_REG_DFBLK       0x3F /* DataFlashBlock */
+#define BQ27541_REG_ADF			0x40
+#define BQ27541_REG_DFDCKS		0x60
+#define BQ27541_REG_DFDCNTL		0x61
+
+#define BQ27541_FLAG_CS_QEN         BIT(0)
+#define BQ27541_FLAG_CS_VOK         BIT(1)
+#define BQ27541_FLAG_CS_RUP_DIS     BIT(2)
+#define BQ27541_FLAG_CS_LDMD        BIT(3)
+#define BQ27541_FLAG_CS_SLEEP       BIT(4)
+#define BQ27541_FLAG_CS_FULLSLEEP   BIT(5)
+#define BQ27541_FLAG_CS_HIBERNATE   BIT(6)
+#define BQ27541_FLAG_CS_SHUTDWN     BIT(7)
+#define BQ27541_FLAG_CS_HDQHOSTIN   BIT(8)
+#define BQ27541_FLAG_CS_RSVD        BIT(9)
+#define BQ27541_FLAG_CS_BCA         BIT(10)
+#define BQ27541_FLAG_CS_CCA         BIT(11)
+#define BQ27541_FLAG_CS_CALMODE     BIT(12)
+#define BQ27541_FLAG_CS_SS          BIT(13)
+#define BQ27541_FLAG_CS_FAS         BIT(14)
+#define BQ27541_FLAG_CS_SE          BIT(15)
+//- jason.kim 2015.12.07 serial number
+
+static DEFINE_MUTEX(battery_mutex);
+
+// host to bq27541
+#define tBreak	   	400	// HDQ Break Time (min 190us)
+#define tBR		    100	// HDQ Break Recovery Time (min 40us)
+#define tHW1        20    // Host sends 1 time (0.5~50us)
+#define tHW0        115    // Host sends 0 time (86~145us)
+#define tCYCH        230    // Host bit window timing (min 190us)
+
+// bq27541 to host
+#define tDW1	    41  // Slave sends 1 time (32~50us)
+#define tDW0	    113	// Slave sends 0 time (80~145us)
+#define tCYCD_T_ONE 60  // FIRST TEST POINT IN CYCD time (max tDW1 50 + alpha)
+#define tCYCD_T_TWO 145 // SECOND TEST POINT AFTER FIRST (max tDW0 145 + alpha)
+#define tRND        210 // Turnaround time
+#define tCYCD       250	// The max of Cycle time of device
+#define tRSPS_HIGH	150
+
+#define tTO		500	// Time-Out Bit Receiption (500us)
+
+#define HDQ_ERROR 0xFFFF // Time-Out Error Condition
+#define BitCount 8 //8 bit
+
+#define BATTERY_FUEL_GAUGER_SEC         10 // 10 secs
+#define BATTERY_FUEL_GAUGER_SEC_LOW     5 // 5 secs
+#define TIMER_HDQ 	400		//About 230us.
+#define BUFFERSIZE  32			//# of bytes for Tx & Rx buffers
+#define ATRATE_MA   -100		// USER CONFIG: AtRate setting (mA)
+#define DEFAULT_CAPACITY    (50)
+#define _KELVIN		2731
+#define TEMP_DEFAULT        (273 + _KELVIN)    // 27.3
+#define TEMP_LIMIT_LOW      (-250 + _KELVIN)   // -25
+#define TEMP_LIMIT_HIGH     (750 + _KELVIN)    // 75C
+
+
+#define NEED_SN_READ 0xBC
+//#define DUMMY_GAUGE
+//#define _FAIL_CNT // [robin.cho] save fail count and read count
+struct bq27541_device_info;
+struct bq27541_access_methods {
+	int (*read)(struct bq27541_device_info *di, u8 reg);
+	int (*write)(struct bq27541_device_info *di, u8 reg, u8 val);
+};
+
+struct bq27541_reg_cache {
+	int temperature;
+	int time_to_empty;
+	//int time_to_empty_avg;
+	//int time_to_full;
+	int charge_full;
+    int cycle_count;
+    int remaining_life;
+	int capacity;
+	int energy;
+	int flags;
+	//int power_avg;
+	int health;
+
+	int voltage_now;
+	int current_now;
+	int charge_now;
+};
+enum bq27541_chip { BQ27541};
+
+/**
+ * struct bq27541_device_data - Platform-dependent data for hdq-gpio
+ * @pin: GPIO pin to use
+ * @is_open_drain: GPIO pin is configured as open drain
+ */
+struct bq27541_device_info {
+	const char *name;
+	unsigned int pin;
+	unsigned int is_open_drain:1;
+	struct device		*dev;
+	int 		id;
+	enum bq27541_chip	chip;
+	struct bq27541_reg_cache cache;
+	int charge_design_full;
+	unsigned long last_update;
+	struct delayed_work battery_work;
+	struct power_supply *bat;
+	spinlock_t   hdq_lock;
+	// struct mutex lock;
+	struct mutex poll_lock; // jason.kim 2015.10.15
+	struct bq27541_access_methods bus;
+	int battery_exist;
+	int battery_init;
+    struct pinctrl *pinctrl;
+    struct pinctrl_state *pinctrl_state_active;
+    // jason.kim 2015.12.07 serial number
+	char serial_no[33];
+	int serial_len;
+#ifdef _FAIL_CNT
+	int fail_count;
+	int read_count;
+	int id_fail_count;
+	int Last_fail_bat_id;
+#endif
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,Begin */
+    int poll_interval;
+    int poll_enable;
+    bool hot_swap;
+	int test_temp_enable; // jason.kim 2016.6.2
+	int test_temp; // jason.kim 2016.3.25 SW temperature control
+
+	// jason.kim 2016.7.12 Test battery capacity
+	int test_cap_enable;
+	int test_cap;
+	int test_health_enable;
+	int test_health;
+
+	// jason.kim 2016.7.18 Test battery voltage
+	int test_voltage_enable;
+	int test_voltage;
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,End */
+
+};
+
+unsigned char *DeviceName;
+/*Add begin Defect-6099797, for HDQ charge safe time */
+int BatteryDesignCap =0;
+/*Add end Defect-6099797, for HDQ charge safe time */
+
+/*
+ *set gpio as input/output
+ *bit = nozero,input,usually bit = 1
+ *bit = 0,output,and default value = 1
+*/
+static inline void hdq_gpio_dir(struct bq27541_device_info *pdata, u8 bit)
+{
+	if (bit)
+		gpio_direction_input(pdata->pin);
+	else
+		gpio_direction_output(pdata->pin, 1);
+}
+
+/* Issue break pulse to the device
+ * Local function to send a HDQ break-transmission for providing a safe
+ * communication start.
+ */
+static inline void gpio_hdq_break(struct bq27541_device_info *pdata)
+{
+	gpio_set_value(pdata->pin, 0);
+	udelay(tBreak);
+	gpio_set_value(pdata->pin, 1);
+	udelay(tBR);
+}
+
+/*
+ *bit = 0,HDQ = 0;which means tHW0 LOW and tCYCH-tHW0 High
+ *bit = 1,HDQ = 1;Which means tHW1 LOW and tCYCH-tHW1 High
+ */
+static inline void gpio_hdq_bit_Write(struct bq27541_device_info *pdata, u8 bit)
+{
+	int tTime;
+	if(bit)
+		tTime = tHW1;
+	else
+		tTime = tHW0;
+
+	gpio_set_value(pdata->pin, 0);
+	udelay(tTime);
+
+	gpio_set_value(pdata->pin, 1);
+	udelay(tCYCH-tTime);
+}
+
+//+ jason.kim 2015.12.01 tidy codes up
+//    Error rates verified with 2 units is around 3 times for around 12 hours
+static void gpio_hdq_byte_Write(struct bq27541_device_info *pdata, u8 val)
+{
+    int i;
+	for(i=0; i<8; i++) {
+		gpio_hdq_bit_Write(pdata, val & (1<<i));
+    }
+}
+
+static int gpio_hdq_byte_read(struct bq27541_device_info *pdata)
+{
+    int i;
+    int bit;
+    int val = 0;
+    ktime_t start, now;
+
+    for(i=0; i<8; i++) {
+        // wait for bit is high
+        start =  ktime_get_real();
+        while(gpio_get_value(pdata->pin)) {
+            now = ktime_get_real();
+            if (ktime_to_us(ktime_sub(now, start)) > tCYCD) {
+#ifdef 	_FAIL_CNT
+                if(pdata->fail_count!=0xFFFFFFFF)
+                   pdata->fail_count++;
+#endif
+                dev_err(pdata->dev, "%s: error\n", __func__);
+                return -1;
+            }
+        }
+        udelay(tCYCD_T_ONE);
+        bit = gpio_get_value(pdata->pin) ? 1 : 0;
+        val = val | (bit << i);
+        udelay(tCYCD_T_TWO-tCYCD_T_ONE);
+    }
+#ifdef 	_FAIL_CNT
+        if(pdata->read_count!=0xFFFFFFFF)
+	   pdata->read_count++;
+#endif
+
+    return val;
+}
+
+static int hdq_gpio_rw(struct bq27541_device_info *pdata, int write, u8 reg, u8 val)
+{
+	unsigned long flags;
+    int value = 0;
+    int t_rnd;
+
+	spin_lock_irqsave(&pdata->hdq_lock, flags);
+
+	hdq_gpio_dir(pdata, 0);// output reg
+	gpio_hdq_break(pdata);
+
+    gpio_hdq_byte_Write(pdata, write ? (reg | 0x80) : (reg & 0x7f));
+
+    if(write) {
+	    udelay(tCYCH);
+        gpio_hdq_byte_Write(pdata, val);
+        t_rnd = tRND;
+
+    } else {
+        hdq_gpio_dir(pdata, 1);// input to read
+        value = gpio_hdq_byte_read(pdata);
+        t_rnd = tRND + tCYCD - tCYCD_T_ONE - tCYCD_T_TWO;
+    }
+
+    spin_unlock_irqrestore(&pdata->hdq_lock, flags);
+    udelay(t_rnd); // jason.kim 2016.9.29 Fixes timing for bq27542
+
+#ifdef DEBUG_HDQ
+    if(value < 0)
+        printk("%s,%d,%d\n",__FUNCTION__,__LINE__, val);
+#endif
+    return value;
+}
+//- jason.kim 2015.12.01 tidy codes up
+
+#if 0 
+//sort for decrease
+static int compare(const void *lhs, const void *rhs) {
+    int lhs_integer = *(const int *)(lhs);
+    int rhs_integer = *(const int *)(rhs);
+
+    if (lhs_integer < rhs_integer) return -1;
+    if (lhs_integer > rhs_integer) return 1;
+    return 0;
+}
+#endif
+
+static inline int hdq_gpio_read(struct bq27541_device_info *di, u8 reg)
+{
+#if 0
+	int try_cnt = 5;
+	int temp_value[5]={0,};
+	int i;
+	for(i=0;i<try_cnt;i++)
+	{
+		temp_value[i] = hdq_gpio_rw(di, 0, reg, 0);
+		//mdelay(5);
+	}
+	sort(temp_value, sizeof(temp_value)/sizeof(int), sizeof(int), &compare, NULL);
+	//dev_err(di->dev, "temp_value[0]0x%x temp_value[1]0x%x temp_value[2]0x%x temp_value[3]0x%x temp_value[4]0x%x  return temp_value[3] 0x%x",temp_value[0],temp_value[1],temp_value[2],temp_value[3],temp_value[4],temp_value[3]);
+	return temp_value[3];
+#else
+	return hdq_gpio_rw(di, 0, reg, 0);
+#endif
+}
+
+static inline int hdq_gpio_write(struct bq27541_device_info *di, u8 reg, u8 val)
+{
+    return hdq_gpio_rw(di, 1, reg, val);
+}
+
+/*
+ * Common code for BQ27541 devices
+ */
+static int bq27541_write8(struct bq27541_device_info *di, u8 reg, u8 val)
+{
+	return di->bus.write(di, reg, val);
+}
+
+static int bq27541_write16(struct bq27541_device_info *di, u8 reg, u16 val)
+{
+    int ret;
+	ret = bq27541_write8(di, reg, val & 0xff);
+	if(ret >= 0)
+        ret = bq27541_write8(di, reg+1, val >> 8);
+	return ret;
+}
+
+static int bq27541_read8(struct bq27541_device_info *di, u8 reg)
+{
+	return di->bus.read(di, reg);
+}
+
+static int bq27541_read16 (struct bq27541_device_info *di, u8 reg)
+{
+    int upper, lower, val;
+
+    upper = bq27541_read8(di, reg+1);
+    if(upper < 0)
+        return upper;
+    lower = bq27541_read8(di, reg);
+    if(lower < 0)
+        return lower;
+
+    val = upper << 8 | lower;
+
+#ifdef DEBUG_HDQ
+    printk("Upper 0x%x, lower 0x%x, ret = 0x%x\n", upper, lower, val);
+#endif
+    return val;
+}
+
+static int bq27541_pinctrl_init(struct bq27541_device_info *di)
+{
+    int ret;
+
+    di->pinctrl = devm_pinctrl_get(di->dev);
+    if (IS_ERR_OR_NULL(di->pinctrl)) {
+        ret = PTR_ERR(di->pinctrl);
+        goto err_pinctrl_get;
+    }
+
+    di->pinctrl_state_active = pinctrl_lookup_state(di->pinctrl, "bq27541_hdq");
+    if (IS_ERR_OR_NULL(di->pinctrl_state_active)) {
+        ret = PTR_ERR(di->pinctrl_state_active);
+        goto err_pinctrl_lookup;
+    }
+
+    ret = pinctrl_select_state(di->pinctrl, di->pinctrl_state_active);
+    if (ret) {
+        return ret;
+    }
+
+    return 0;
+
+err_pinctrl_lookup:
+    devm_pinctrl_put(di->pinctrl);
+
+err_pinctrl_get:
+    di->pinctrl = NULL;
+
+    return ret;
+}
+
+//+ jason.kim 2015.12.07 serial number
+static int set_mfg_block(struct bq27541_device_info *di, int sealed)
+{
+	u8 block = 1;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	if (sealed) {
+		block = 2;
+	} else {
+		int dfd_cntl_status = 0;
+        dfd_cntl_status = bq27541_read8(di, BQ27541_REG_DFDCNTL);
+		if (dfd_cntl_status != 0) {
+            bq27541_write8(di, BQ27541_REG_DFDCNTL, 0);
+		}
+        bq27541_write8(di, BQ27541_REG_DFCLS, 58);
+		block = 1;
+	}
+
+    bq27541_write8(di, BQ27541_REG_DFBLK, block);
+	msleep(1);
+	return 0;
+}
+
+#ifdef USE_SERIAL_32_BYTES
+#define SERIAL_BYTES     32
+#if 0
+static int is_good_serial(char *serial)
+{
+    int i;
+    for(i=0; i<SERIAL_BYTES; i++) {
+        if(!isalnum(serial[i]))
+            return 0;
+    }
+
+    return 1;
+}
+#endif
+#endif
+
+static void bq27541_battery_read_serial(struct bq27541_device_info *di)
+{
+    int flags;
+    int data;
+	u8 sum = 0;
+	int sealed = 0;
+	int serial_len;
+	int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+    udelay(66);
+    flags = bq27541_read16(di, BQ27541_REG_CNTL);
+//	di->serial_len = 0;
+	sealed = (flags & BQ27541_FLAG_CS_SS) == BQ27541_FLAG_CS_SS;
+	if (flags < 0 || set_mfg_block(di, sealed)) {
+	    dev_err(di->dev, "set_mfg_block failed\n");
+		return;
+	}
+
+#ifdef USE_SERIAL_32_BYTES
+    serial_len = SERIAL_BYTES;
+	sum = 0;
+#else
+    serial_len = bq27541_read8(di, BQ27541_REG_ADF);
+	sum = serial_len;
+#endif
+	if (serial_len <= 0 || serial_len > 32) {
+	    dev_err(di->dev, "serial_len %d is not valid\n", serial_len);
+		return;
+	}
+
+	memset(di->serial_no, 0, sizeof(di->serial_no));
+	for (i = 0; i < serial_len; i++) {
+#ifdef USE_SERIAL_32_BYTES
+        data = bq27541_read8(di, BQ27541_REG_ADF + i);
+#else
+        data = bq27541_read8(di, BQ27541_REG_ADF + i + 1);
+#endif
+//		dev_err(di->dev, "## data 0x%x \n", data);
+
+        if(data < 0) {
+	        dev_info(di->dev, "Read %ith failed\n", i);
+            return;
+        }
+        di->serial_no[i] = (char)data;
+		sum += di->serial_no[i];
+	}
+
+    data = bq27541_read8(di, BQ27541_REG_DFDCKS);
+    sum += data;
+	if (data < 0 || sum != 0xFF) {
+	    dev_err(di->dev, "check-sum 0x%x data 0x%x error \n", sum , data);
+		return;
+	}
+#ifdef USE_SERIAL_32_BYTES
+	if( di->serial_no[0]<=0)
+	{
+	    dev_err(di->dev, "serial number:error ::di->serial_no[0] 0x%x  di->serial_len 0x%x\n",di->serial_no[0],di->serial_len );
+		return;
+		
+	}
+#endif
+	di->serial_len = serial_len;
+}
+
+static int bq27541_battery_write_serial(struct bq27541_device_info *di, const char* serial_no)
+{
+	u8 sum = 0;
+	int sealed = 0;
+	int serial_len = strlen(serial_no);
+    u8 buf_w[32], buf_v[32];
+	int i;
+	int flags = 0;
+    int data;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	if (serial_len && serial_no[serial_len-1] == 0x0a) {
+		serial_len = serial_len - 1;
+	}
+
+#ifdef USE_SERIAL_32_BYTES
+    if(serial_len != SERIAL_BYTES) {
+	    dev_err(di->dev, "serial_len %d(%d) is not valid\n", serial_len, SERIAL_BYTES);
+        return 0;
+    }
+#endif
+
+	if (serial_len <= 0 || serial_len > 32) {
+	    dev_err(di->dev, "serial_len %d is not valid\n", serial_len);
+		return 0;
+	}
+
+    bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+    udelay(66);
+    flags = bq27541_read16(di, BQ27541_REG_CNTL);
+	sealed = (flags & BQ27541_FLAG_CS_SS) == BQ27541_FLAG_CS_SS;
+	if (flags < 0 || set_mfg_block(di, sealed)) {
+	    dev_err(di->dev, "set_mfg_block failed\n");
+		return 0;
+	}
+
+#ifdef USE_SERIAL_32_BYTES
+	memset(buf_w, 0, sizeof(buf_w));
+    memcpy(buf_w, serial_no, serial_len);
+	dev_info(di->dev, "Write serial [%s] to battery\n", buf_w);
+#else
+    // prepare data
+	memset(buf_w, 0, sizeof(buf_w));
+    buf_w[0] = serial_len;
+    memcpy(buf_w+1, serial_no, serial_len);
+	dev_info(di->dev, "Write serial [%s] to battery\n", buf_w+1);
+#endif
+
+    // write it to battery
+	for (i = 0; i < sizeof(buf_w); i++) {
+        bq27541_write8(di, BQ27541_REG_ADF+i, buf_w[i]);
+		sum += buf_w[i];
+	}
+	sum = 0xff - sum;
+
+    // read it back
+	memset(buf_v, 0, sizeof(buf_w));
+	for (i = 0; i < sizeof(buf_w); i++) {
+        data = bq27541_read8(di, BQ27541_REG_ADF + i);
+        if(data < 0) {
+	        dev_info(di->dev, "Read %ith failed\n", i);
+            return 0;
+        }
+        buf_v[i] = (char)data;
+	}
+
+    // check it
+    if(memcmp(buf_w, buf_v, sizeof(buf_w))) {
+	    dev_err(di->dev, "Verification failed\n");
+		return 0;
+    }
+    // write check-sum to battery
+	dev_info(di->dev, "Check-sum=0x%x\n", sum);
+    bq27541_write8(di, BQ27541_REG_DFDCKS, sum);
+	msleep(200);
+	return serial_len;
+}
+//- jason.kim 2015.12.07 serial number
+
+//+ jason.kim 2015.12.08 dump MFG-B
+#define DUMP_COL 16
+static void dump_bin(u8 *buf, int size)
+{
+    int i, j;
+    int lc;
+    char line[DUMP_COL];
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	pr_info("========================\n");
+    for(lc=0, i=0; i<size; i++) {
+        pr_cont( "%02X ", buf[i]);
+        line[lc++] = buf[i];
+
+        if((i+1)%DUMP_COL == 0) {
+            lc=0;
+            for(j=0; j<DUMP_COL; j++) {
+                if(line[j] >= ' ' && line[j] <= '~')
+                    pr_cont( "%c", line[j]);
+                else
+                    pr_cont( ".");
+            }
+	        pr_cont("\n");
+        }
+    }
+	pr_info("========================\n");
+}
+
+static void bq27541_battery_dump_mfg_B(struct bq27541_device_info *di)
+{
+    int flags;
+    int data;
+	u8 sum = 0;
+	int sealed = 0;
+    char serial_no[32];
+	int serial_len;
+	int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+    udelay(66);
+    flags = bq27541_read16(di, BQ27541_REG_CNTL);
+	di->serial_len = 0;
+	sealed = (flags & BQ27541_FLAG_CS_SS) == BQ27541_FLAG_CS_SS;
+	if (flags < 0 || set_mfg_block(di, sealed)) {
+	    dev_err(di->dev, "set_mfg_block failed\n");
+		return;
+	}
+
+    serial_len = 32;
+	for (i = 0; i < serial_len; i++) {
+        data = (char)bq27541_read8(di, BQ27541_REG_ADF + i);
+        if(data < 0) {
+	        dev_info(di->dev, "Read %ith failed\n", i);
+            return;
+        }
+        serial_no[i] = (char)data;
+		sum += serial_no[i];
+	}
+    data = bq27541_read8(di, BQ27541_REG_DFDCKS);
+    if(data < 0) {
+        dev_info(di->dev, "Read check-sum failed\n");
+        return;
+    }
+
+    dump_bin((u8 *)serial_no, 32);
+	dev_info(di->dev, "Check sum=0x%x(0x%x)\n", sum, data);
+}
+//- jason.kim 2015.12.08 dump MFG-B
+
+//+ jason.kim 2016.01.20 Check and update battery parameters
+static int bq27541_get_sealing(struct bq27541_device_info *di)
+{
+    int flags;
+	int sealed;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+    udelay(66);
+    flags = bq27541_read16(di, BQ27541_REG_CNTL);
+	dev_info(di->dev, "flags 0x%X\n", flags);
+	sealed = (flags & BQ27541_FLAG_CS_SS) == BQ27541_FLAG_CS_SS;
+	if (flags < 0) {
+	    dev_err(di->dev, "Failed to read BQ27541_REG_CNTL\n");
+        return flags;
+	}
+    return sealed;
+}
+
+static int bq27541_set_sealing(struct bq27541_device_info *di, int sealing)
+{
+	int sealed;
+    int ret;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    if (sealing) {
+        bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_SEALED);
+        msleep(200);
+        bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+        udelay(66);
+    } else {
+        bq27541_write16(di, BQ27541_REG_CNTL, 0x0414);
+        bq27541_write16(di, BQ27541_REG_CNTL, 0x3672);
+        msleep(100);
+        bq27541_write16(di, BQ27541_REG_CNTL, BQ27541_SUBCMD_CTNL_STATUS);
+        udelay(66);
+    }
+
+    sealed = bq27541_get_sealing(di);
+    ret = (sealed == sealed) ? 0 : -1;
+    if(ret < 0)
+        dev_err(di->dev, "Failed to set sealing(%d)\n", sealing);
+
+    return ret;
+}
+
+static int bq27541_rw_block(struct bq27541_device_info *di, int subcmd, int offset)
+{
+    int ret;
+
+    	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    ret = bq27541_write8(di, BQ27541_REG_DFCLS, subcmd);
+    if (ret >= 0)
+        ret = bq27541_write8(di, BQ27541_REG_DFBLK, offset / 32);
+    if (ret >= 0)
+        ret = bq27541_write8(di, BQ27541_REG_DFDCNTL, 0);
+    return ret;
+}
+
+static int bq27541_rw_flash(struct bq27541_device_info *di, int subcmd, int offset, u8 *buf, int bytes, int write)
+{
+    int ret;
+    int i;
+    	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    ret = bq27541_rw_block(di, subcmd, offset);
+    if (ret < 0)
+        return ret;
+
+    // i must be less then 32
+    for(i = offset%32; i < (offset%32 + bytes); i++) {
+        if(write) {
+            ret = bq27541_write8(di, BQ27541_REG_ADF + i, *buf++);
+            if (ret < 0)
+                return ret;
+        } else {
+            ret = bq27541_read8(di, BQ27541_REG_ADF + i);
+            if (ret < 0)
+                return ret;
+            *buf++ = (u8)ret;
+        }
+    }
+    return 0;
+}
+
+static int bq27541_read_flash16(struct bq27541_device_info *di, int subcmd, int offset)
+{
+    int ret;
+    u8 buf[2];
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    ret = bq27541_rw_flash(di, subcmd, offset, buf, 2, 0);
+    if (ret < 0)
+        return ret;
+
+    return ((int)buf[0] << 8) | buf[1];
+}
+
+__attribute__ ((unused)) static int bq27541_write_flash16(struct bq27541_device_info *di, int subcmd, int offset, int data)
+{
+    u8 buf[2];
+    buf[0] = (data >> 8) & 0xff;
+    buf[1] = data & 0xff;
+
+    return bq27541_rw_flash(di, subcmd, offset, buf, 2, 1);
+}
+
+static int bq27541_battery_reset_param(struct bq27541_device_info *di)
+{
+    int ret;
+    u8 buf[34] = {
+        0x0A,0xF0,0x00,0x0A,0x05,0x00,0x32,0x01,0xC2,0x14,0x14,0x00,0x08,0x09,0xF6,0x00,
+        0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+    };
+    u8 sum;
+    int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    ret = bq27541_set_sealing(di, 0); // unseal
+    if (ret < 0)
+        return ret;
+
+    bq27541_rw_flash(di, 68, 0, buf, 32, 1);
+    sum = 0;
+    for (i=0; i<32; i++) {
+        sum += buf[i];
+    }
+    sum = 0xff - sum;
+    bq27541_write8(di, BQ27541_REG_DFDCKS, sum);
+    msleep(200);
+    bq27541_rw_flash(di, 68, 0, buf, 32, 0);
+    dump_bin(buf, 32);
+    di->battery_init = 0;
+
+    ret = bq27541_set_sealing(di, 1); // seal
+    if (ret < 0)
+        return ret;
+    return 0;
+}
+
+static int bq27541_battery_init_param(struct bq27541_device_info *di)
+{
+    int ret;
+    int h_current = 0;
+    int h_voltage = 0;
+    u8 buf[34];
+    u8 sum;
+    int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    ret = bq27541_set_sealing(di, 0); // unseal
+    if (ret < 0)
+        return ret;
+
+    h_current = bq27541_read_flash16(di, 68, 11);
+    h_voltage = bq27541_read_flash16(di, 68, 13);
+    dev_info(di->dev, "Current %d, Voltage %d\n", h_current, h_voltage);
+    if(h_current != 0 || h_voltage != 0) {
+        bq27541_rw_flash(di, 68, 0, buf, 32, 0);
+        dump_bin(buf, 32);
+        buf[11] = 0;
+        buf[12] = 0;
+        buf[13] = 0;
+        buf[14] = 0;
+        bq27541_rw_flash(di, 68, 0, buf, 32, 1);
+        sum = 0;
+        for (i=0; i<32; i++) {
+            sum += buf[i];
+        }
+        sum = 0xff - sum;
+        bq27541_write8(di, BQ27541_REG_DFDCKS, sum);
+        msleep(200);
+        h_current = bq27541_read_flash16(di, 68, 11);
+        h_voltage = bq27541_read_flash16(di, 68, 13);
+        if(h_current == 0 && h_voltage == 0)
+            di->battery_init = 1;
+        dev_info(di->dev, "Current %d, Voltage %d\n", h_current, h_voltage);
+    } else {
+        di->battery_init = 1;
+    }
+    bq27541_rw_flash(di, 68, 0, buf, 32, 0);
+    dump_bin(buf, 32);
+    ret = bq27541_set_sealing(di, 1); // seal
+    if (ret < 0)
+        ret = bq27541_set_sealing(di, 1); // seal
+    if (ret < 0)
+        ret = bq27541_set_sealing(di, 1); // seal
+
+    return ret;
+}
+//- jason.kim 2016.01.20 Check and update battery parameters
+
+static int bq27541_simple_value(int value,
+	union power_supply_propval *val)
+{
+	if (value < 0)
+		return value;
+
+	val->intval = value;
+
+	return 0;
+}
+#if 0
+static int bq27541_s16_value(int value, union power_supply_propval *val)
+{
+	if (value < 0)
+		return value;
+
+    val->intval = (int)((s16)value);
+	return 0;
+}
+#endif
+static int bq27541_battery_read_id(struct bq27541_device_info *di)
+{
+    int retry = 5;
+    int value;
+#ifdef DEBUG_BQ
+	printk("zxz   -------  %s ,line=%d \n", __FUNCTION__,__LINE__);
+		dev_err(di->dev, "zxz   bq27541_battery_read_id\n");
+#endif
+#if 0
+        bq27541_write16(di, bq27541CMD_CNTL_LSB, BQ27541_SUBCMD_DEVCIE_TYPE); // this code removed by robin.cho
+        value = bq27541_read16(di, bq27541CMD_CNTL_LSB);
+	retry=0;
+#else
+    do {
+        bq27541_write16(di, bq27541CMD_CNTL_LSB, BQ27541_SUBCMD_DEVCIE_TYPE);
+        value = bq27541_read16(di, bq27541CMD_CNTL_LSB);
+		//mdelay(100);
+
+    } while((value !=BQ27542_DEVICE_ID) && retry--);
+    #endif
+#ifdef DEBUG_BQ
+		dev_err(di->dev, "zxz   bq27541_battery_read_id , value=%x ,retry=%d \n",value,retry);
+	printk("zxz   -------  %s ,line=%d  ,value=%x \n", __FUNCTION__,__LINE__,value);
+#endif
+    return value;
+}
+
+/*
+ * Return the battery average current in µA
+ * Note that current can be negative signed as well
+ * Or 0 if something fails.
+ */
+static int bq27541_battery_read_current(struct bq27541_device_info *di)
+{
+	int curr;
+	curr = bq27541_read16(di, bq27541CMD_AI_LSB);
+	if(curr < 0){
+        dev_err(di->dev, "error reading curr\n");
+	}
+    return curr;
+}
+
+/*
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
+ */
+static int bq27541_battery_read_cc(struct bq27541_device_info *di)
+{
+	int cyct;
+
+	cyct = bq27541_read16(di, bq27541CMD_CC_LSB);
+	if (cyct < 0)
+		dev_err(di->dev, "error reading cycle count total\n");
+
+	return cyct;
+}
+#if 0
+
+/*
+ * Read a power avg register.
+ * Return < 0 if something fails.
+ */
+static int bq27541_battery_read_pwr_avg(struct bq27541_device_info *di, u8 reg)
+{
+	int tval;
+
+	tval = bq27541_read16(di, reg, reg+1);
+	if (tval < 0) {
+		dev_err(di->dev, "error reading power avg rgister  %02x: %d\n",
+			reg, tval);
+		return tval;
+	}
+	return tval;
+}
+#endif
+
+/*
+ * Higher versions of the chip like BQ27425 and BQ27500
+ * differ from BQ27000 and BQ27200 in calculation of certain
+ * parameters. Hence we need to check for the chip type.
+ */
+static bool bq27xxx_is_chip_version_higher(struct bq27541_device_info *di)
+{
+
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	if (di->chip == BQ27541)
+		return true;
+	return false;
+}
+
+/*Remove by T2M Q.Z for PR1003449
+* Do not use status detection from bq27541.
+* Use smb1357 status detection.
+*/
+/*
+static int bq27541_battery_status(struct bq27541_device_info *di,
+	union power_supply_propval *val)
+{
+	int status;
+
+	if(di->battery_exist == 0)
+		status = POWER_SUPPLY_STATUS_UNKNOWN;
+	else{
+		if (bq27xxx_is_chip_version_higher(di)) {
+			if (di->cache.flags & BQ27541_FLAG_FC)
+				status = POWER_SUPPLY_STATUS_FULL;
+			else if (di->cache.flags & BQ27541_FLAG_DSC)
+				status = POWER_SUPPLY_STATUS_DISCHARGING;
+			else
+				status = POWER_SUPPLY_STATUS_CHARGING;
+		}
+	}
+	val->intval = status;
+
+	return 0;
+}
+*/
+
+/*
+* get FLAGS from bq27541. many marker bits in the FLAGS.
+* FC means full-charged . OTC means Over-Temperature and so on.
+*/
+static int bq27541_get_battery_flags(struct bq27541_device_info *di)
+{
+    int flags;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    flags = bq27541_read16(di, bq27541CMD_FLAGS_LSB);
+    if (flags < 0){
+        dev_err(di->dev, "error reading flags\n");
+    }
+
+    return flags;
+}
+
+static int bq27541_battery_read_volt(struct bq27541_device_info *di)
+{
+	int volt;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line = %d\n",__FUNCTION__,__LINE__);
+	#endif
+	volt = bq27541_read16(di, bq27541CMD_VOLT_LSB);
+	if (volt < 0) {
+        dev_err(di->dev, "error reading voltage\n");
+        return volt;
+	}
+
+	return volt *1000;
+}
+
+/*
+ * Return a battery charge value in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27541_battery_read_charge(struct bq27541_device_info *di, u8 reg)
+{
+	int charge;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line =%d \n",__FUNCTION__,__LINE__);
+	#endif
+	charge = bq27541_read16(di, reg);
+	if (charge < 0) {
+		dev_dbg(di->dev, "error reading charge \n");
+		return charge;
+	}
+
+	if (bq27xxx_is_chip_version_higher(di))
+		charge *= 1000;
+
+	return charge;
+}
+
+/*
+ * Return the battery FullChargeCapacity in mAh
+ * Or < 0 if something fails.
+ */
+static inline int bq27541_battery_read_fcc(struct bq27541_device_info *di)
+{
+	return bq27541_battery_read_charge(di, bq27541CMD_FCC_LSB);
+}
+
+
+/*
+ * Return the battery Nominal available capaciy in µAh
+ * Or < 0 if something fails.
+ */
+static int bq27541_battery_read_nac(struct bq27541_device_info *di)
+{
+	int charge;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line =%d \n",__FUNCTION__,__LINE__);
+	#endif
+	charge = bq27541_read16(di, bq27541CMD_NAC_LSB);
+	if (charge < 0) {
+		dev_err(di->dev, "error reading NAC\n");
+		return charge;
+	}
+
+    return charge * 1000;
+}
+
+/*
+ * Return the battery Relative State-of-Charge
+ * Or = 0xff if something fails.
+ */
+static int bq27541_battery_read_rsoc(struct bq27541_device_info *di)
+{
+	int rsoc;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line =%d \n",__FUNCTION__,__LINE__);
+	#endif
+	rsoc = bq27541_read16(di, bq27541CMD_SOC_LSB);
+	if (rsoc < 0){
+        dev_err(di->dev, "error reading State-of-Charge:CAPACITY\n");
+        return rsoc;
+	}
+
+	return rsoc;
+}
+
+/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27541_battery_read_energy(struct bq27541_device_info *di)
+{
+	int ae;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line =%d \n",__FUNCTION__,__LINE__);
+	#endif
+	ae = bq27541_read16(di, bq27541CMD_AE_LSB);
+	if (ae < 0) {
+		dev_err(di->dev, "error reading available energy\n");
+		return ae;
+	}
+
+	if (di->chip == BQ27541)
+		ae *= 1000;
+
+	return ae;
+}
+
+/*
+ * Read flag register.
+ * Return < 0 if something fails.
+ */
+// START removed by chase.jang(2018.04.18)
+// unsed function
+#if 0
+static int bq27541_battery_read_health(struct bq27541_device_info *di)
+{
+	int tval;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line = %d\n",__FUNCTION__,__LINE__);
+	#endif
+	tval = bq27541_read16(di, bq27541CMD_FLAGS_LSB);
+	if (tval < 0) {
+        dev_err(di->dev, "error reading health\n");
+        return tval;
+	}
+
+	if (tval & BQ27541_FLAG_SOCF)
+		tval = POWER_SUPPLY_HEALTH_DEAD;
+	else if (tval & BQ27541_FLAG_OTC)
+		tval = POWER_SUPPLY_HEALTH_OVERHEAT;
+	else if (tval & BQ27541_FLAG_OTD) // for overtemperature when discharging
+		tval = POWER_SUPPLY_HEALTH_OVERHEAT;
+	else
+		tval = POWER_SUPPLY_HEALTH_GOOD;
+	return tval;
+}
+#endif
+// END
+
+static int get_health_from_qpnp_smbcharger(struct bq27541_device_info *di)
+{
+	struct power_supply * bms_supply = NULL;
+	union power_supply_propval prop = {0,};
+	/*
+		char *str_power_supply[]=
+	{
+		"POWER_SUPPLY_HEALTH_UNKNOWN",
+		"POWER_SUPPLY_HEALTH_GOOD",
+		"POWER_SUPPLY_HEALTH_OVERHEAT",
+		"POWER_SUPPLY_HEALTH_DEAD",
+		"POWER_SUPPLY_HEALTH_OVERVOLTAGE",
+		"POWER_SUPPLY_HEALTH_UNSPEC_FAILURE",
+		"POWER_SUPPLY_HEALTH_COLD",
+		"POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_WARM",
+		"POWER_SUPPLY_HEALTH_COOL",
+	};*/
+/*
+		chip->bms_psy =
+			power_supply_get_by_name((char *)chip->bms_psy_name);
+	if (chip->bms_psy) {
+		chip->bms_psy->get_property(chip->bms_psy,
+				POWER_SUPPLY_PROP_BATTERY_TYPE, &prop);
+		en = (strcmp(prop.strval, UNKNOWN_BATT_TYPE) != 0
+				|| chip->charge_unknown_battery)
+			&& (strcmp(prop.strval, LOADING_BATT_TYPE) != 0);
+		vote(chip->battchg_suspend_votable,
+				BATTCHG_UNKNOWN_BATTERY_EN_VOTER, !en, 0);
+		*/
+
+	bms_supply = power_supply_get_by_name("battery");
+	if(bms_supply == NULL)
+	{
+		 dev_err(di->dev, "robin.cho]can't get battery-SO return goood status----------\n");
+		 return POWER_SUPPLY_HEALTH_GOOD;
+	}
+	else
+	{
+		power_supply_get_property(bms_supply,POWER_SUPPLY_PROP_HEALTH, &prop);
+		//dev_err(di->dev, "robin.cho]  health status %s\n",str_power_supply[prop.intval]);
+	}
+	return prop.intval;
+}
+
+/*
+ * Return the battery temperature in tenths of degree Kelvin
+ * Or < 0 if something fails.
+ */
+ 
+static int bq27541_battery_read_temperature(struct bq27541_device_info *di)
+{
+
+#ifdef NOT_USE_HDQ_TEMPERATURE
+		struct power_supply * bms_supply = NULL;
+		union power_supply_propval prop = {0,};
+		bms_supply = power_supply_get_by_name("bms");
+		if(bms_supply == NULL)
+		{
+			 dev_err(di->dev, "robin.cho]can't get bms-SO Defaut temp 27.3C----------\n");
+			 return TEMP_DEFAULT;
+		}
+		else
+		{
+			power_supply_get_property(bms_supply,POWER_SUPPLY_PROP_TEMP, &prop);
+			// dev_err(di->dev, "robin.cho]can get bms temp %d----------\n",prop.intval);
+		}
+		return prop.intval+_KELVIN;
+
+#else
+	return bq27541_read16(di,bq27541CMD_TEMP_LSB);
+#endif
+}
+
+/*
+ * Return the battery design capacity in mAh
+ * Or < 0 if something fails.
+ */
+static int bq27541_battery_read_dcap(struct bq27541_device_info *di)
+{
+	int ilmd;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line =%d \n",__FUNCTION__,__LINE__);
+	#endif
+	if (bq27xxx_is_chip_version_higher(di))
+		ilmd = bq27541_read16(di, bq27541CMD_DCAP_LSB);
+
+	if (ilmd < 0) {
+		dev_err(di->dev, "error reading DESIGN CAPACITY\n");
+		return ilmd;
+	}
+
+	if (bq27xxx_is_chip_version_higher(di))
+		ilmd *= 1000;
+	return ilmd;
+}
+
+/*
+ * Return remaining life (unit : %)
+ */
+static int bq27541_battery_read_remaining_life(struct bq27541_device_info *di)
+{
+    int remaining_life = 0;
+
+    remaining_life = bq27541_read16(di, bq27541CMD_SOH_LSB);
+    if ((remaining_life < 0) || (remaining_life > 100))
+        dev_err(di->dev, "error reading remaining_life\n");
+
+    return remaining_life;
+}
+// jason.kim 2015.11.23 use remap table
+#ifdef USE_REMAP_TABLE
+static int bq27541_battery_capacity(struct bq27541_device_info *di,
+	union power_supply_propval *val)
+{
+    const char remap_capacity[101] = {
+	    0,   0,   0,   0,   1,   3,   4,   5,   7,   8,
+	    9,  10,  12,  14,  15,  16,  18,  19,  20,  22,
+	    23,  24,  26,  27,  28,  30,  31,  32,  34,  35,
+	    36,  38,  39,  41,  42,  43,  45,  46,  47,  49,
+	    51,  52,  53,  54,  55,  56,  57,  58,  59,  60,
+	    61,  62,  63,  64,  65,  66,  67,  68,  69,  70,
+	    71,  72,  73,  74,  75,  76,  77,  78,  79,  80,
+	    81,  82,  83,  84,  85,  86,  87,  88,  90,  90,
+	    91,  91,  92,  92,  93,  93,  94,  94,  95,  95,
+	    96,  96,  97,  97,  98,  99,  99, 100, 100, 100,
+	    100
+    };
+    int rsoc = di->cache.capacity;
+
+	if (rsoc < 0 || rsoc > 100)
+		return -1;
+
+    rsoc = remap_capacity[rsoc];
+    val->intval = rsoc;
+  //  printk("%s: rsoc %d => %d\n", __func__, di->cache.capacity, rsoc); // MODIFIED by liquan.zhou, 2018-09-08,BUG-6904042
+	return 0;
+}
+#elif defined(USE_SW_TUNE)
+// jason.kim 2015.11.21 fake capacity
+#define CAPACITY_0      4
+#define CAPACITY_100    97
+#define CAPACITY_CUT    (CAPACITY_0 + (100 - CAPACITY_100 + 1))
+static int bq27541_battery_capacity(struct bq27541_device_info *di,
+	union power_supply_propval *val)
+{
+    int rsoc = di->cache.capacity;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+		dev_err(di->dev, "zxz  %s , Line = %d\n",__FUNCTION__,__LINE__);
+	#endif
+	if (rsoc < 0)
+		return rsoc;
+
+    if(rsoc >= CAPACITY_100) {
+        rsoc = 100;
+    } else {
+        rsoc = rsoc * (100+CAPACITY_CUT) / 100 - CAPACITY_0;
+        if(rsoc < 0)
+            rsoc = 0;
+        if(rsoc > 100)
+            rsoc = 100;
+    }
+
+    val->intval = rsoc;
+    printk("%s: rsoc %d => %d\n", __func__, di->cache.capacity, rsoc);
+    return 0;
+}
+#else
+// jason.kim 2015.11.27 Reports original capacity
+static int bq27541_battery_capacity(struct bq27541_device_info *di,
+	union power_supply_propval *val)
+{
+    int rsoc = di->cache.capacity;
+    	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+			dev_err(di->dev, "zxz  %s , Line = %d\n",__FUNCTION__,__LINE__);
+	#endif
+    val->intval = rsoc;
+    return rsoc;
+}
+#endif
+
+static int bq27541_battery_capacity_level(struct bq27541_device_info *di,
+	union power_supply_propval *val)
+{
+	int level;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	dev_err(di->dev, "zxz  %s , Line = %d\n",__FUNCTION__,__LINE__);
+	#endif
+	if (bq27xxx_is_chip_version_higher(di)){
+		if (di->cache.flags & BQ27541_FLAG_FC)
+			level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+		else if (di->cache.flags & BQ27541_FLAG_SOC1)
+			level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+		else if (di->cache.flags & BQ27541_FLAG_SOCF)
+			level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+		else
+			level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+	}
+
+	val->intval = level;
+
+	return 0;
+}
+
+/*
+ * Read a time register.
+ * Return < 0 if something fails.
+ */
+static int bq27541_battery_read_time(struct bq27541_device_info *di, u8 reg)
+{
+	int tval;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	tval = bq27541_read16(di, reg);
+	if (tval < 0) {
+		dev_err(di->dev, "error reading time register\n");
+		return tval;
+	}
+	return tval;
+}
+
+
+// jason.kim 2015.11.12
+#define CAPACITY_0_CHECK_COUNT 4 // [2018/05/28 robin.cho]Add for issue #12070
+static void bq27541_update(struct bq27541_device_info *di)
+{
+
+
+    struct bq27541_reg_cache cache = {0, };
+    int battery_exist;
+    int value;
+    int value2;
+    int bat_id;
+    static int CAPACITY_0_check=0;//[2018/05/28 robin.cho]Add for issue #12070
+    if(di->cache.flags == 0)
+ 	di->cache.flags = 0x100;
+
+    cache = di->cache;
+
+#ifdef DEBUG_BQ
+	printk("zxz   -------  %s ,line=%d \n", __FUNCTION__,__LINE__);
+#endif
+
+#ifdef DEBUG_BQ
+	dev_err(di->dev, "zxz  111 bq27541_update\n");
+#endif
+	bat_id=0;
+	bat_id = bq27541_battery_read_id(di);
+    battery_exist = (bat_id == BQ27542_DEVICE_ID);
+    #ifdef DEBUG_BQ
+	dev_err(di->dev, "zxz 222  bq27541_update\n");
+#endif
+
+
+#if 1
+	/*get HDQ flags*/
+	value = bq27541_get_battery_flags(di);
+	if(value >= 0) {
+        cache.flags = value;
+    }
+    #ifdef DEBUG_BQ
+    	dev_err(di->dev, "zxz 333  bq27541_update\n");
+#endif
+#endif
+
+#ifdef DEBUG_BQ
+    	dev_err(di->dev, "zxz  444 bq27541_update\n");
+   #endif
+    if(battery_exist != di->battery_exist) {
+		di->battery_exist = battery_exist;
+        if(di->battery_exist) {
+            printk("%s: Battery is detected\n", __func__);
+        } else {
+            printk("%s: Battery is not detected\n", __func__);
+#ifdef _FAIL_CNT
+			if(di->id_fail_count!=0xFFFFFFFF)
+			di->id_fail_count++;
+			di->Last_fail_bat_id=bat_id;
+#endif
+	        di->serial_len = NEED_SN_READ; // jason.kim 2015.12.07 srial number
+            di->battery_init = 0;
+            di->poll_interval = BATTERY_FUEL_GAUGER_SEC_LOW;
+            goto battery_not_exist;
+        }
+    }
+#ifdef DEBUG_BQ
+	printk("zxz   -------  %s ,line=%d , battery_exist=%d  \n", __FUNCTION__,__LINE__,battery_exist);
+#endif
+    // jason.kim 2015.12.07 srial number
+    if(battery_exist) {
+    /*Defect-6099592 no need read battery serial number*/
+#if 1
+        if(di->serial_len==NEED_SN_READ) {
+            bq27541_battery_read_serial(di);
+            //dev_info(di->dev, "Serial=%s\n", di->serial_len ? di->serial_no : "unknown");
+        }
+#endif
+        // jason.kim 2016.01.20 Check and update battery parameters
+        if(!di->battery_init) {
+            bq27541_battery_init_param(di);
+        }
+    }
+	/*get HDQ flags*/
+	value = bq27541_get_battery_flags(di);
+	if(value >= 0) {
+        cache.flags = value;
+    }
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.flags = 0x%x\n",__FUNCTION__,__LINE__,cache.flags);
+	    	dev_err(di->dev, "zxz  5555 bq27541_update, cache.flags=%d\n",cache.flags);
+#endif
+
+	/*get voltage*/
+	value = bq27541_battery_read_volt(di);
+	if( (value >= 0) && (value < 4400000) ) {
+		cache.voltage_now = value;
+	}
+
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.voltage_now = %d\n",__FUNCTION__,__LINE__,cache.voltage_now);
+		    	dev_err(di->dev, "zxz  6666 bq27541_update, cache.voltage_now=%d\n",cache.voltage_now);
+
+#endif
+
+	/*get current*/
+	value = bq27541_battery_read_current(di);
+	if(value >= 0) {
+        cache.current_now = value;
+    }
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.voltage_now = %d\n",__FUNCTION__,__LINE__,cache.current_now);
+	dev_err(di->dev, "zxz  77777 bq27541_update, cache.current_now=%d\n",cache.current_now);
+#endif
+
+    // jason.kim 2015.11.27 check capacity error
+	/*capacity*/
+	value = bq27541_battery_read_rsoc(di);
+	if(value >= 0) {
+	   msleep(10);
+           value2 = bq27541_battery_read_rsoc(di);
+	    if( value2 >=0 && abs(value2 - value) <= 1 && value >= 0 && value<=100 ) {
+          // +(2018.05.28 robin.cho)
+	  //  [issue #12070] if battery gauge chip reporting as 0 percent,we check it 4 times because gauge chip sometime wrong value reporting
+	         if( value == 0 ) {
+	             ++CAPACITY_0_check;
+#ifdef DEBUG_UPDATE_VALUE
+		         dev_info(di->dev, "robin.cho]%s,%d,CAPACITY_0_check = %d value = %d value2 = %d\n",__FUNCTION__,__LINE__,CAPACITY_0_check,value,value2);
+#endif
+                 if(CAPACITY_0_check >= CAPACITY_0_CHECK_COUNT ) {
+	                 CAPACITY_0_check = 0;
+	                 cache.capacity = value;
+	             }
+	        }else {
+	            CAPACITY_0_check = 0;
+                cache.capacity = value;
+	        }
+	        //-(2018.05.28 robin.cho)
+	    }
+       }
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.capacity = %d\n",__FUNCTION__,__LINE__,cache.capacity);
+	dev_err(di->dev, "zxz  8888 bq27541_update, cache.capacity=%d\n",cache.capacity);
+#endif
+
+	/*get available energy*/
+	value = bq27541_battery_read_energy(di);
+	if(value >= 0){
+		cache.energy = value;
+	}
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.energy = %d\n",__FUNCTION__,__LINE__,cache.energy);
+	dev_err(di->dev, "zxz  9999 bq27541_update, cache.energy=%d\n",cache.energy);
+#endif
+
+	/*get nominal available capacity*/
+	value = bq27541_battery_read_nac(di);
+	if(value >= 0){
+		cache.charge_now = value;
+	}
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.charge_now = %d\n",__FUNCTION__,__LINE__,cache.charge_now);
+	dev_err(di->dev, "zxz  AAAAA bq27541_update, cache.charge_now=%d\n",cache.charge_now);
+#endif
+#if 0
+	/*get health*/
+	value = bq27541_battery_read_health(di);
+	if(value >= 0){
+		cache.health = value;
+	}
+#endif
+	cache.health = get_health_from_qpnp_smbcharger(di); // get battery health status smbcharger
+
+
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.health = %d\n",__FUNCTION__,__LINE__,cache.health);
+	dev_err(di->dev, "zxz  BBBB bq27541_update, cache.health=%d\n",cache.health);
+#endif
+
+    // jason.kim 2015.11.27 check temperature error
+	/*get temperature*/
+	value = bq27541_battery_read_temperature(di);
+	if(value >= 0) {
+	    msleep(10);
+	    value2 = bq27541_battery_read_temperature(di);
+        if( abs(value2-value) <= 10 && value >= TEMP_LIMIT_LOW && value <= TEMP_LIMIT_HIGH ) {
+            cache.temperature = value;
+        } else {
+		    if(di->cache.temperature == 0)
+                cache.temperature = TEMP_DEFAULT;
+        }
+	}
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.temperature = %d\n",__FUNCTION__,__LINE__,cache.temperature);
+	dev_err(di->dev, "zxz  CCCC bq27541_update, cache.temperature=%d\n",cache.temperature);
+#endif
+
+	/*get fcc*/
+	value = bq27541_battery_read_fcc(di);
+	if(value >= 0 ){
+		cache.charge_full = value;
+	}
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.charge_full = %d\n",__FUNCTION__,__LINE__,cache.charge_full);
+	dev_err(di->dev, "zxz  DDDD bq27541_update, cache.charge_full=%d\n",cache.charge_full);
+#endif
+
+    /* time to empty */
+	value =	bq27541_battery_read_time(di,bq27541CMD_TTE_LSB);
+	if(value >= 0) {
+		cache.time_to_empty = value;
+	}
+#ifdef DEBUG_UPDATE_VALUE
+	printk("%s,%d,cache.time_to_empty = %d\n",__FUNCTION__,__LINE__,cache.time_to_empty);
+	dev_err(di->dev, "zxz  EEEE bq27541_update, cache.time_to_empty=%d\n",cache.time_to_empty);
+#endif
+
+	/*Modified by T2M Q.Z
+	* For 3000mah/4000mah change.
+	*/
+
+battery_not_exist:
+	if(!battery_exist){
+		cache.capacity = DEFAULT_CAPACITY;
+/*Modify-Begin ,task-5373326 ,T2M zxz,2017/10/20, power off when use fake battery*/
+		cache.voltage_now = 3800000;
+/*Modify-End ,task-5373326 ,T2M zxz,2017/10/20, power off when use fake battery*/
+		cache.energy = 0;
+		cache.charge_now = 0;
+		cache.health = POWER_SUPPLY_HEALTH_UNKNOWN;
+/*Add-BEGIN by T2M.xcm. 2015.5.15 1003151 power off auto.*/
+		cache.temperature = TEMP_DEFAULT;
+//Add-END by T2M.xcm
+		cache.charge_full = 0;
+		cache.time_to_empty = 0;
+	}
+    value = bq27541_battery_read_cc(di);
+    if(value >= 0) {
+        cache.cycle_count = value;
+    }
+#ifdef DEBUG_UPDATE_VALUE
+    dev_info(di->dev, "%s,%d,cycle_count = %d\n",__FUNCTION__,__LINE__, cache.cycle_count);
+#endif
+	value = bq27541_battery_read_remaining_life(di);
+    if(value >= 0) {
+        cache.remaining_life = value;
+    }
+#ifdef DEBUG_UPDATE_VALUE
+    dev_info(di->dev, "%s,%d,remaining_life = %d\n",__FUNCTION__,__LINE__, cache.remaining_life);
+#endif
+
+#ifdef DUMMY_GAUGE
+		cache.capacity = DEFAULT_CAPACITY;
+/*Modify-Begin ,task-5373326 ,T2M zxz,2017/10/20, power off when use fake battery*/
+		cache.voltage_now = 3800000;
+/*Modify-End ,task-5373326 ,T2M zxz,2017/10/20, power off when use fake battery*/
+		cache.energy = 0;
+		cache.charge_now = 0;
+		cache.health = POWER_SUPPLY_HEALTH_UNKNOWN;
+/*Add-BEGIN by T2M.xcm. 2015.5.15 1003151 power off auto.*/
+		cache.temperature = TEMP_DEFAULT;
+//Add-END by T2M.xcm
+		cache.charge_full = 0;
+		cache.time_to_empty = 0;
+
+#endif
+#ifdef _FAIL_CNT
+	dev_err(di->dev, "zxz battery_exist %d cache.capacity %d cache.voltage_now %d cache.charge_now %d cache.temperature %d fail_count %d read_count %d ,id_fail_count %d Last_fail_bat_id 0x%x\n",battery_exist,cache.capacity,cache.voltage_now,cache.charge_now,cache.temperature,di->fail_count,di->read_count,di->id_fail_count,di->Last_fail_bat_id);
+#endif
+	if(memcmp(&di->cache, &cache, sizeof(cache)) != 0){
+		di->cache = cache;
+		power_supply_changed(di->bat);
+	}
+}
+
+static void bq27541_battery_poll(struct work_struct *work)
+{
+	struct bq27541_device_info *di =
+		container_of(work, struct bq27541_device_info, battery_work.work);
+
+#ifdef DEBUG_BQ
+	printk("++%s, %d\n",__FUNCTION__ , __LINE__);
+      dev_err(di->dev, "zxz  bq27541_battery_poll  Begin  \n");
+
+#endif
+#ifdef ZXZ_BQ27541
+      dev_err(di->dev, "zxz  bq27541_battery_poll  Begin  \n");
+#endif
+    // jason.kim 2015.10.15 for canceling the polling
+	mutex_lock(&di->poll_lock);
+
+    if (di->poll_enable) {
+        if (!di->hot_swap)
+            bq27541_update(di);
+        schedule_delayed_work(&di->battery_work, di->poll_interval * HZ);
+	}
+	mutex_unlock(&di->poll_lock);
+
+#ifdef DEBUG_BQ
+    dev_info(di->dev, "--%s, %d\n",__FUNCTION__ , __LINE__);
+#endif
+#ifdef ZXZ_BQ27541
+	dev_err(di->dev, "zxz  bq27541_battery_poll  End \n");
+#endif
+}
+
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,Begin */
+static void bq27541_battery_poll_start(struct bq27541_device_info *di, int ptime)
+{
+    mutex_lock(&di->poll_lock);
+    di->poll_enable = 1;
+    mutex_unlock(&di->poll_lock);
+    dev_info(di->dev, "%s: schedule_delayed_work\n", __func__);
+    schedule_delayed_work(&di->battery_work, ptime * HZ);
+}
+
+static void bq27541_battery_poll_stop(struct bq27541_device_info *di)
+{
+    mutex_lock(&di->poll_lock);
+    di->poll_enable = 0;
+    mutex_unlock(&di->poll_lock);
+    if (delayed_work_pending(&di->battery_work)) {
+        dev_info(di->dev, "%s: cancel_delayed_work\n", __func__);
+        cancel_delayed_work_sync(&di->battery_work);
+    }
+}
+
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,End */
+
+
+static int bq27541_battery_is_writeable(struct power_supply *psy,
+				       enum power_supply_property prop)
+{
+	int rc;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	switch (prop) {
+	case POWER_SUPPLY_PROP_CAPACITY:
+		rc = 1;
+		break;
+	default:
+		rc = 0;
+		break;
+	}
+	return rc;
+}
+
+static int bq27541_battery_get_property(struct power_supply *psy,
+					enum power_supply_property psp,
+					union power_supply_propval *val)
+{
+	int ret = 0;
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+	if (di->cache.flags < 0)
+	{
+		#ifdef DEBUG_BQ
+		printk("%s, %d ,return error !\n", __FUNCTION__,__LINE__);
+		#endif
+		return -ENODEV;
+	}
+
+	switch (psp) {
+    case POWER_SUPPLY_PROP_PRESENT: // jason.kim 2015.10.15 report the battery present (POWER_SUPPLY_PROP_PRESENT)
+        if (di->test_cap_enable)
+            val->intval = 1;
+        else
+            val->intval = di->battery_exist;
+        break;
+
+
+	/*Remove by T2M Q.Z for PR1003449
+	* Do not use status detection from bq27541.
+	* Use smb1357 status detection.
+	*/
+	//case POWER_SUPPLY_PROP_STATUS:
+	//	ret = bq27541_battery_status(di, val);
+	//	break;
+
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		if(di->battery_exist)
+			val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		else
+			val->intval = POWER_SUPPLY_TECHNOLOGY_UNKNOWN;
+		break;
+
+	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+        if (di->test_voltage_enable)
+    		ret = bq27541_simple_value(di->test_voltage, val);
+		else
+			ret = bq27541_simple_value(di->cache.voltage_now, val);
+
+		break;
+
+	case POWER_SUPPLY_PROP_CURRENT_NOW:
+		//ret = bq27541_s16_value(di->cache.current_now, val);
+		val->intval = (int)(s16)bq27541_battery_read_current(di);
+        val->intval *= 1000; // uA
+		break;
+
+	case POWER_SUPPLY_PROP_CAPACITY:
+        if (di->test_cap_enable) {
+            val->intval = di->test_cap;
+        } else {
+            ret = bq27541_battery_capacity(di, val);
+        }
+        if (val->intval < 20 || di->cache.current_now <= 0) // low battery or charging
+            di->poll_interval = BATTERY_FUEL_GAUGER_SEC_LOW;
+        else
+            di->poll_interval = BATTERY_FUEL_GAUGER_SEC;
+		break;
+
+	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+		ret = bq27541_battery_capacity_level(di, val);
+		break;
+
+	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
+        if (di->cache.time_to_empty == 65535)
+            val->intval = -1; // jason.kim 2015.11.16 for suppressing debug message
+        else
+            ret = bq27541_simple_value(di->cache.time_to_empty * 60, val);
+		break;
+
+	//case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
+	//	ret = bq27541_simple_value(di->cache.time_to_empty_avg, val);
+	//	break;
+
+	//case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
+	//	ret = bq27541_simple_value(di->cache.time_to_full, val);
+	//	break;
+
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		ret = bq27541_simple_value(di->charge_design_full, val);
+		break;
+
+	//case POWER_SUPPLY_PROP_CYCLE_COUNT:
+	//	ret = bq27541_simple_value(di->cache.cycle_count, val);
+	//	break;
+
+	//case POWER_SUPPLY_PROP_POWER_AVG:
+	//	ret = bq27541_simple_value(di->cache.power_avg, val);
+	//	break;
+
+	case POWER_SUPPLY_PROP_TEMP:
+		if (di->test_temp_enable) {
+		   ret = bq27541_simple_value(di->test_temp, val);
+		}
+		else
+		{
+		   ret = bq27541_simple_value(di->cache.temperature, val);
+		}
+		val->intval -= _KELVIN; //  swich kelvin to Celsius
+		break;
+
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		ret = bq27541_simple_value(di->cache.charge_now, val);
+		break;
+
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		ret = bq27541_simple_value(di->cache.energy, val);
+		break;
+
+	case POWER_SUPPLY_PROP_HEALTH:
+		if (di->test_health_enable)
+			val->intval =  di->test_health;
+		else
+			ret = bq27541_simple_value(di->cache.health, val);
+		break;
+
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		ret = bq27541_simple_value(di->cache.charge_full, val);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,prop=%d ; val->intval=%d\n", __FUNCTION__,__LINE__,psp,val->intval);
+#endif
+
+
+	return ret;
+
+}
+
+static int bq27541_battery_set_property(struct power_supply *psy,
+				       enum power_supply_property prop,
+				       const union power_supply_propval *val)
+{
+	int rc = 0, update_psy = 0;
+    struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	switch (prop) {
+		case POWER_SUPPLY_PROP_CAPACITY:
+			di->cache.capacity = val->intval;
+			update_psy = 1;
+			break;
+		default:
+			rc = -EINVAL;
+	}
+
+	if (!rc && update_psy)
+		power_supply_changed(di->bat);
+	return rc;
+}
+
+//+ jason.kim 2015.11.24 dump registers
+static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	
+    int value;
+    char *_buf = buf;
+
+    bq27541_battery_poll_stop(di);
+
+    value = bq27541_read16(di, BQ27541_REG_CNTL);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_CNTL, value);
+    value = bq27541_read16(di, BQ27541_REG_AR);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_AR, value);
+    value = bq27541_read16(di, BQ27541_REG_UFSOC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_UFSOC, value);
+    value = bq27541_read16(di, BQ27541_REG_TEMP);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_TEMP, value);
+    value = bq27541_read16(di, BQ27541_REG_VOLT);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_VOLT, value);
+    value = bq27541_read16(di, BQ27541_REG_FLAGS);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_FLAGS, value);
+    value = bq27541_read16(di, BQ27541_REG_NAC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_NAC, value);
+    value = bq27541_read16(di, BQ27541_REG_FAC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_FAC, value);
+    value = bq27541_read16(di, BQ27541_REG_RM);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_RM, value);
+    value = bq27541_read16(di, BQ27541_REG_FCC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_FCC, value);
+    value = bq27541_read16(di, BQ27541_REG_AI);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_AI, value);
+    value = bq27541_read16(di, BQ27541_REG_TTE);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_TTE, value);
+    value = bq27541_read16(di, BQ27541_REG_FFCC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_FFCC, value);
+    value = bq27541_read16(di, BQ27541_REG_SI);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_SI, value);
+    value = bq27541_read16(di, BQ27541_REG_UFFCC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_UFFCC, value);
+    value = bq27541_read16(di, BQ27541_REG_MLI);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_MLI, value);
+    value = bq27541_read16(di, BQ27541_REG_UFRM);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_UFRM, value);
+    value = bq27541_read16(di, BQ27541_REG_FRM);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_FRM, value);
+    value = bq27541_read16(di, BQ27541_REG_AP);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_AP, value);
+
+    value = bq27541_read16(di, BQ27541_REG_INTTEMP);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_INTTEMP, value);
+    value = bq27541_read16(di, BQ27541_REG_CC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_CC, value);
+    value = bq27541_read16(di, BQ27541_REG_SOC);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_SOC, value);
+    value = bq27541_read16(di, BQ27541_REG_SOH);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_SOH, value);
+
+    value = bq27541_read16(di, BQ27541_REG_PCHG);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_PCHG, value);
+    value = bq27541_read16(di, BQ27541_REG_DOD0);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_DOD0, value);
+/*Add begin Defect-6099797, for HDQ charge safe time */
+    value = bq27541_read16(di, 0x3c);
+    buf += sprintf(buf, "%02X %04X\n", 0x3c, value);
+/*Add end Defect-6099797, for HDQ charge safe time */
+    value = bq27541_read16(di, BQ27541_REG_SDSG);
+    buf += sprintf(buf, "%02X %04X\n", BQ27541_REG_SDSG, value);
+
+    bq27541_battery_poll_start(di, 0);
+	return (buf-_buf);
+}
+
+//+ jason.kim 2015.12.07 serial number
+static ssize_t store_serial_no(struct device *dev,  struct device_attribute *attr, const char *buf,  size_t count)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	if (!di->battery_exist)
+        return 0;
+
+    bq27541_battery_poll_stop(di);
+
+    bq27541_battery_write_serial(di, buf);
+    bq27541_battery_read_serial(di);
+    dev_info(di->dev, "Serial=%s\n", di->serial_len ? di->serial_no : "unknown");
+
+    bq27541_battery_poll_start(di, 0);
+    return count;
+}
+
+static ssize_t show_serial_no(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+#ifdef USE_SERIAL_32_BYTES
+  printk("%s######\n", __func__);
+
+	if(di->serial_len == NEED_SN_READ)
+	{
+		return sprintf(buf, "%s\n","unknown");
+	}
+	else
+	{
+	
+		PM85_SERIAL *serial_number;
+		serial_number = (PM85_SERIAL *)di->serial_no;
+		
+        printk( "%s::%d######di->serial_len 0x%x\n", __func__,__LINE__,di->serial_len);
+		if(di->serial_len != NEED_SN_READ)
+		{
+//			char str_serial[20]={0,};
+//			char str_manufacture_date[20]={0,};
+			printk("%s::%d  :di->serial_len 0x%x ###### SN : %s MF %s\n", __func__,__LINE__,di->serial_len ,serial_number->SN,serial_number->MF_date);	
+
+//			memcpy((void *)str_serial , (void *)serial_number->SN,serial_number->length_SN);
+//			memcpy((void *)str_manufacture_date , (void *)serial_number->MF_date,serial_number->length_MF_date);
+//			printk( "%s::%d###### SN : %s MF %s\n", __func__,__LINE__,str_serial,str_manufacture_date);		
+			return sprintf(buf,"%s-%s\n",serial_number->SN,serial_number->MF_date);
+
+		
+		}else
+		{
+			return sprintf(buf,"%s\n","unknown");
+
+		}
+    //	return sprintf(buf, "%s\n", (di->serial_len && is_good_serial(di->serial_no)) ? di->serial_no : "unknown");
+	}
+#else
+	if(di->serial_len == NEED_SN_READ)
+	{
+		return sprintf(buf, "%s\n","unknown");
+	}
+	else
+	{
+  	  return sprintf(buf, "%s\n", di->serial_len ? di->serial_no : "unknown");
+	}
+#endif
+}
+//+ jason.kim 2015.12.07 serial number
+
+//+ jason.kim 2015.12.08 dump MFG-B
+static ssize_t show_mfg_b(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+		#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+    bq27541_battery_dump_mfg_B(di);
+    return 0;
+}
+//- jason.kim 2015.12.08 dump MFG-B
+
+// jason.kim 2016.01.20 Check and update battery parameters
+static ssize_t show_reset_battery(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+    bq27541_battery_poll_stop(di);
+    bq27541_battery_reset_param(di);
+    bq27541_battery_poll_start(di, 0);
+    return 0;
+}
+
+static ssize_t show_battery_remaining_life(struct device *dev,struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+    return sprintf(buf, "%d\n", di->cache.remaining_life);
+}
+static ssize_t show_battery_cycle_count(struct device *dev,struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+    return sprintf(buf, "%d\n", di->cache.cycle_count);
+}
+static ssize_t show_real_soc(struct device *dev, struct device_attribute *attr, char *buf) //  it add for stress test tool
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+    return sprintf(buf, "%d", di->cache.capacity);
+}
+
+//+ jason.kim 2016.3.24 test temperature control
+static ssize_t store_test_temp(struct device *dev,  struct device_attribute *attr, const char *buf,  size_t count)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    int param, ret;
+    ret = kstrtoint(buf, 10, &param);
+    if (ret < 0)
+        return count;
+
+    // jason.kim 2016.6.2
+    if (param == 1000) {
+        di->test_temp_enable = 0;
+        di->test_temp = 300+ _KELVIN;
+    } else if (param == 1001) {
+        di->test_temp_enable = 1;
+        di->test_temp = 300+_KELVIN;
+    } else
+        di->test_temp = param + _KELVIN;
+        dev_info(di->dev, "temp=%d\n", di->test_temp - _KELVIN);
+    return count;
+}
+
+static ssize_t show_test_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    return sprintf(buf, "test_temp %d\n", di->test_temp - _KELVIN);
+}
+//- jason.kim 2016.3.24 test temperature control
+
+//+ jason.kim 2016.7.12 Test battery capacity
+static ssize_t store_test_cap(struct device *dev,  struct device_attribute *attr, const char *buf,  size_t count)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    int param, ret;
+    ret = kstrtoint(buf, 10, &param);
+    if (ret < 0)
+        return count;
+
+    // jason.kim 2016.6.2
+    if (param == 1000) {
+        di->test_cap_enable = 0;
+        di->test_cap = 50;
+    } else if (param == 1001) {
+        di->test_cap_enable = 1;
+        di->test_cap = 50;
+    } else
+        di->test_cap = param;
+
+    dev_info(di->dev, "test_cap =%d\n", di->test_cap);
+    return count;
+}
+
+static ssize_t show_test_cap(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    return sprintf(buf, "test_cap %d\n", di->test_cap);
+}
+//- jason.kim 2016.7.12 Test battery capacity
+
+//+ jason.kim 2016.7.18 Test battery voltage
+static ssize_t store_test_voltage(struct device *dev,  struct device_attribute *attr, const char *buf,  size_t count)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    int param, ret;
+    ret = kstrtoint(buf, 10, &param);
+    if (ret < 0)
+        return count;
+
+    // jason.kim 2016.6.2
+    if (param == 1000) {
+        di->test_voltage_enable = 0;
+        di->test_voltage = 3700 * 1000;
+    } else if (param == 1001) {
+        di->test_voltage_enable = 1;
+        di->test_voltage = 3700 * 1000;
+    } else
+        di->test_voltage = param * 1000;
+    dev_info(di->dev, "test_voltage =%d\n", di->test_voltage / 1000);
+    return count;
+}
+
+static ssize_t show_test_voltage(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    return sprintf(buf, "test_voltage %d\n", di->test_voltage / 1000);
+}
+//- jason.kim 2016.7.18 Test battery voltage
+
+static ssize_t store_test_health(struct device *dev,  struct device_attribute *attr, const char *buf,  size_t count)
+{
+	char *str_power_supply[]=
+	{
+		"POWER_SUPPLY_HEALTH_UNKNOWN",
+		"POWER_SUPPLY_HEALTH_GOOD",
+		"POWER_SUPPLY_HEALTH_OVERHEAT",
+		"POWER_SUPPLY_HEALTH_DEAD",
+		"POWER_SUPPLY_HEALTH_OVERVOLTAGE",
+		"POWER_SUPPLY_HEALTH_UNSPEC_FAILURE",
+		"POWER_SUPPLY_HEALTH_COLD",
+		"POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_WARM",
+		"POWER_SUPPLY_HEALTH_COOL",
+	};
+
+	struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    int param, ret;
+    ret = kstrtoint(buf, 10, &param);
+    if (ret < 0)
+        return count;
+
+    // jason.kim 2016.6.2
+    if (param == 1000) {
+        di->test_health_enable = 0;
+        di->test_health = POWER_SUPPLY_HEALTH_GOOD;
+    } else if (param == 1001) {
+         di->test_health_enable = 1;
+        di->test_health = POWER_SUPPLY_HEALTH_GOOD;
+    } else
+    {
+    	if(param >10)
+    	{
+   		 	dev_info(di->dev, "Error input param %d \n", param);
+       		return count;
+    	}
+		else
+        	di->test_health = param;
+    }
+
+    dev_info(di->dev, "Enable:: %d  test_health =%d [%s]\n",  di->test_health_enable ,di->test_health ,str_power_supply[di->test_health]);
+    return count;
+}
+
+static ssize_t show_test_health(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	char *str_power_supply[]=
+	{
+		"POWER_SUPPLY_HEALTH_UNKNOWN",
+		"POWER_SUPPLY_HEALTH_GOOD",
+		"POWER_SUPPLY_HEALTH_OVERHEAT",
+		"POWER_SUPPLY_HEALTH_DEAD",
+		"POWER_SUPPLY_HEALTH_OVERVOLTAGE",
+		"POWER_SUPPLY_HEALTH_UNSPEC_FAILURE",
+		"POWER_SUPPLY_HEALTH_COLD",
+		"POWER_SUPPLY_HEALTH_WATCHDOG_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE",
+		"POWER_SUPPLY_HEALTH_WARM",
+		"POWER_SUPPLY_HEALTH_COOL",
+	};
+    struct power_supply *psy = dev_get_drvdata(dev);
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+    return sprintf(buf, "Enable:: %d test_health =%d [%s]\n", di->test_health_enable , di->test_health ,str_power_supply[di->test_health]);
+}
+
+
+
+static struct device_attribute bq27541_battery_attrs[] = {
+	__ATTR(dump_regs, 0444, show_dump_regs, NULL), // jason.kim 2015.03.02 dump all registers
+	__ATTR(serial_no, 0664, show_serial_no, store_serial_no), // jason.kim 2015.12.07 serial number
+	__ATTR(mfg_b, 0444, show_mfg_b, NULL), // jason.kim 2015.12.08 dump MFG-B
+	__ATTR(reset, 0444, show_reset_battery, NULL), // jason.kim 2016.01.20 Check and update battery parameters
+    __ATTR(remaining_life, S_IRUGO, show_battery_remaining_life, NULL),
+    __ATTR(cycle_count, S_IRUGO, show_battery_cycle_count, NULL),
+    __ATTR(real_soc, 0444, show_real_soc, NULL), // [robin.cho] it add for strees test tool:show real SOC
+    __ATTR(test_temp, 0664, show_test_temp, store_test_temp), // jason.kim 2016.3.25 SW temperature control
+    __ATTR(test_cap, 0664, show_test_cap, store_test_cap), // jason.kim 2016.7.12 Test battery capacity
+    __ATTR(test_voltage, 0664, show_test_voltage, store_test_voltage), // jason.kim 2016.7.18 Test battery voltage
+    __ATTR(test_health, 0664, show_test_health, store_test_health), // robin.cho
+};
+
+static int bq27541_create_attrs(struct device *dev)
+{
+	unsigned int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	for (i = 0; i < ARRAY_SIZE(bq27541_battery_attrs); i++)
+		if (device_create_file(dev, &bq27541_battery_attrs[i]))
+			goto bq27541_create_attrs_failed;
+
+	return 0;
+
+bq27541_create_attrs_failed:
+	dev_err(dev, "failed creating bq27541 battery attrs.\n");
+	while (i--)
+		device_remove_file(dev, &bq27541_battery_attrs[i]);
+
+	return -EIO;
+}
+
+static void bq27541_remove_attrs(struct device *dev)
+{
+	unsigned int i;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	for (i = 0; i < ARRAY_SIZE(bq27541_battery_attrs); i++)
+		device_remove_file(dev, &bq27541_battery_attrs[i]);
+}
+//- jason.kim 2015.11.24 dump registers
+
+
+
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,Begin */
+void bq27541_poll_stop(struct power_supply *psy)
+{
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	bq27541_battery_poll_stop(di);
+}
+
+int bq27541_read_rsoc(struct power_supply *psy)
+{
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	return bq27541_battery_read_rsoc(di);
+}
+
+int bq27541_read_temp(struct power_supply *psy)
+{
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+	return bq27541_battery_read_temperature(di);
+}
+
+
+
+//void bq24086_set_lowbattery(bool low_battery);
+void bq27541_set_hot_swap(struct power_supply *psy, int low_battery)
+{
+	struct bq27541_device_info *di = power_supply_get_drvdata(psy);
+
+	//bq24086_set_lowbattery(low_battery);
+	if (low_battery) {
+		di->hot_swap = true;
+        bq27541_battery_poll_stop(di);
+        di->battery_exist = 0;
+        di->serial_len = NEED_SN_READ;
+        //di->serial_retry = 0;
+        di->battery_init = 0;
+	   di->poll_interval = BATTERY_FUEL_GAUGER_SEC_LOW;
+        power_supply_changed(di->bat);
+	} else {
+		di->hot_swap = false;
+        bq27541_battery_poll_start(di, 0);
+	}
+
+}
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875,End */
+
+static const struct power_supply_desc batt_psy_desc = {
+	.name = "bq27541_battery",
+	.type = POWER_SUPPLY_TYPE_BATTERY,
+	.properties = bq27541_battery_props,
+	.num_properties = ARRAY_SIZE(bq27541_battery_props),
+	.get_property = bq27541_battery_get_property,
+	.set_property = bq27541_battery_set_property,
+	.property_is_writeable = bq27541_battery_is_writeable,
+};
+
+static int bq27541_powersupply_init(struct bq27541_device_info *di)
+{
+
+	struct power_supply_config batt_cfg = {};
+	int ret = 0;
+	
+    #ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+    #endif
+
+	batt_cfg.drv_data = di;
+	batt_cfg.of_node = di->dev->of_node;
+	di->bat = devm_power_supply_register(di->dev,
+					   &batt_psy_desc,
+					   &batt_cfg);
+	if (IS_ERR(di->bat)) {
+		pr_err("Couldn't register battery power supply bq27541 !\n");
+		return PTR_ERR(di->bat);
+	}
+
+	#ifdef DEBUG_BQ
+	printk("%s,%d\n",__FUNCTION__,__LINE__);
+	#endif
+
+	#ifdef _FAIL_CNT
+	di->read_count=0;
+	di->fail_count=0;
+	di->id_fail_count=0;
+	di->Last_fail_bat_id=0;
+	#endif
+
+	
+	INIT_DELAYED_WORK(&di->battery_work, bq27541_battery_poll);
+	// mutex_init(&di->lock);
+
+    // jason.kim 2015.11.24 dump registers
+    ret = bq27541_create_attrs(di->dev);
+    if (ret) {
+        dev_err(di->dev, "fail to create main sysfs: %d\n", ret);
+        return ret;
+    }
+	return 0;
+}
+
+static int hdq_parse_dt(struct platform_device *pdev,
+			struct bq27541_device_info *pdata)
+{
+    //int rc;
+	struct device_node *np = pdev->dev.of_node;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	pdata->pin = of_get_named_gpio(np,"qcom,hdq-gpio", 0);
+	if(!pdata->pin){
+		dev_err(&pdev->dev, "Unable to get hdq_gpio\n");
+		return -ENODEV;
+	}
+
+	pdev->dev.platform_data = pdata;
+
+	return 0;
+}
+
+static int bq27541_probe(struct platform_device *pdev)
+{
+	int err;
+	int value;
+	struct bq27541_device_info *di = pdev->dev.platform_data;
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "failed to allocate device info data\n");
+		return  -ENOMEM;
+	}
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 00000000000 \n", __FUNCTION__,__LINE__);
+#endif
+	platform_set_drvdata(pdev, di); // jason.kim 2015.10.15
+
+	/*hdq parse dt*/
+	err = hdq_parse_dt(pdev,di);
+	if (err < 0) {
+		dev_err(&pdev->dev, "Failed to parse DT\n");
+		return err;
+	}
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 11111111 \n", __FUNCTION__,__LINE__);
+#endif
+	/*request gpio*/
+	if(gpio_is_valid(di->pin)){
+		err = gpio_request(di->pin, "hdq");
+		if (err) {
+			dev_err(&pdev->dev, "gpio_request (pin) failed\n");
+			goto free_gpio;
+		}
+	}
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 22222222222 ---di->pin =%d \n", __FUNCTION__,__LINE__,di->pin);
+#endif
+	mutex_init(&di->poll_lock); // jason.kim 2015.10.15
+	spin_lock_init(&di->hdq_lock);
+
+	/* timer */
+	//my_timer->data = 0xff;
+	//my_timer->function = &timer_function;
+	//my_timer->expires = jiffies + HZ/10000;
+	//init_timer(my_timer);
+
+	/*fill the struct*/
+	di->battery_exist = 0;
+	di->dev = &pdev->dev;
+	di->chip = BQ27541;
+	di->bus.read = &hdq_gpio_read;
+	di->bus.write = &hdq_gpio_write;
+	di->poll_interval = BATTERY_FUEL_GAUGER_SEC;
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 3333333 \n", __FUNCTION__,__LINE__);
+#endif
+
+    err=bq27541_pinctrl_init(di);
+	if(err)
+	dev_err(di->dev, " bq27541_pinctrl_init failed \n");
+
+	err = bq27541_powersupply_init(di);
+	if (err)
+		goto err_free;
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 4444444444444 \n", __FUNCTION__,__LINE__);
+#endif
+#ifdef DEBUG_INIT_VALUE
+    dev_info(di->dev, "Initial capacity %d, current %d\n",
+        bq27541_battery_read_rsoc(di),
+        (int)((s16)bq27541_battery_read_current(di)));
+#endif
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe 555555555 \n", __FUNCTION__,__LINE__);
+#endif
+
+/*Add begin Defect-6099797, for HDQ charge safe time */
+    value = bq27541_battery_read_dcap(di);
+	if(value >= 0)
+        di->charge_design_full = value;
+        BatteryDesignCap=di->charge_design_full;
+	printk(" %s,%d,BatteryDesignCap = %d\n",__FUNCTION__,__LINE__,BatteryDesignCap);
+/*Add end Defect-6099797, for HDQ charge safe time */
+
+	di->serial_len = NEED_SN_READ;
+
+
+    bq27541_battery_poll_start(di, 0);
+	dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+
+#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe success !!!!!!\n", __FUNCTION__,__LINE__);
+#endif
+
+	return 0;
+
+ err_free:
+	 kfree(di);
+	 #ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe FAIL !!!!!!\n", __FUNCTION__,__LINE__);
+	#endif
+	 return err;
+
+ free_gpio:
+	gpio_free(di->pin);
+	#ifdef DEBUG_BQ
+	printk("%s ,line=%d ,probe FAIL !!!!!!\n", __FUNCTION__,__LINE__);
+	#endif
+	return err;
+}
+
+// jason.kim 2015.10.15
+static int bq27541_remove(struct platform_device *pdev)
+{
+	struct bq27541_device_info *di = dev_get_drvdata(&pdev->dev);
+
+#ifdef DEBUG_BQ
+    printk("%s,%d\n",__FUNCTION__,__LINE__);
+#endif
+    bq27541_battery_poll_stop(di);
+
+    bq27541_remove_attrs(di->dev); // jason.kim 2015.11.24 dump registers
+	power_supply_unregister(di->bat);
+	// mutex_destroy(&di->lock);
+	mutex_destroy(&di->poll_lock);
+	gpio_free(di->pin);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(di);
+
+	return 0;
+}
+
+static int bq27541_battery_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bq27541_device_info *di = platform_get_drvdata(pdev);
+
+	dev_info(dev, "++%s\n", __func__);
+
+    bq27541_battery_poll_stop(di);
+
+	dev_info(dev, "--%s\n", __func__);
+	return 0;
+}
+
+
+static int bq27541_battery_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct bq27541_device_info *di = platform_get_drvdata(pdev);
+
+	#ifdef DEBUG_BQ
+	printk("%s, %d,  \n",__FUNCTION__ , __LINE__);
+	#endif
+
+
+/* PLATFORM]-add by T2MNB.ZXZ,add hotswap feature,2018/06/27,defect-6502875 */
+	if(!di->hot_swap) {
+		bq27541_battery_poll_start(di, 0);
+	}
+	dev_info(dev, "--%s\n", __func__);
+	return 0;
+}
+//-- jason.kim 2015.10.15
+
+static const struct dev_pm_ops bq27541_battery_pm_ops = {
+		 .suspend		 = bq27541_battery_suspend,
+		 .resume		 = bq27541_battery_resume,
+};
+
+static struct of_device_id hdq_gpio_dt_ids[] = {
+	{ .compatible = "qcom,bq27541-fuel-hdq" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, hdq_gpio_dt_ids);
+
+static struct platform_driver bq27541_driver = {
+	.driver = {
+		.name	= "bq27541",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(hdq_gpio_dt_ids),
+		.pm = &bq27541_battery_pm_ops,
+	},
+	.probe = bq27541_probe,
+	.remove = bq27541_remove,
+};
+
+module_platform_driver(bq27541_driver);
+
+MODULE_DESCRIPTION("GPIO HDQ driver");
+MODULE_AUTHOR("AaronZeng <qiang.zeng@T2mobile.com>");
+MODULE_LICENSE("GPL");