فهرست منبع

Version 1.4.0_20170728-0628 released

Jenkins 8 سال پیش
والد
کامیت
8e29c980d8

+ 1 - 1
drivers/misc/mediatek/alsps/alsps_factory.c

@@ -22,7 +22,7 @@ static long alsps_factory_unlocked_ioctl(struct file *file, unsigned int cmd, un
 	long err = 0;
 	struct alsps_context *cxt = alsps_context_obj;
 	void __user *ptr = (void __user *) arg;
-	int dat;
+	int dat = 0;
 	uint32_t enable = 0;
 	int ps_cali = 0;
 	int threshold_data[2];

+ 58 - 40
drivers/misc/mediatek/gpu/ged/src/ged_main.c

@@ -96,12 +96,18 @@ static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM)
     void *pvInt, *pvOut;
     typedef int (ged_bridge_func_type)(void*, void*);
     ged_bridge_func_type* pFunc = NULL;
-    
-    if ((psBridgePackageKM->i32InBufferSize >=0) && (psBridgePackageKM->i32OutBufferSize >=0) &&
-        (psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize < GED_IOCTL_PARAM_BUF_SIZE))
-    {
-        pvInt = gvIOCTLParamBuf;
-        pvOut = (void*)((char*)pvInt + (uintptr_t)psBridgePackageKM->i32InBufferSize);
+
+	/* We make sure the both size and the sum of them are GE 0 integer.
+	 * The sum will not overflow to zero, because we will get zero from two GE 0 integers
+	 * if and only if they are both zero in a 2's complement numeral system.
+	 * That is: if overflow happen, the sum will be a negative number.
+	 */
+	if (psBridgePackageKM->i32InBufferSize >= 0 && psBridgePackageKM->i32OutBufferSize >= 0
+		&& psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize >= 0
+		&& psBridgePackageKM->i32InBufferSize + psBridgePackageKM->i32OutBufferSize
+		< GED_IOCTL_PARAM_BUF_SIZE) {
+		pvInt = gvIOCTLParamBuf;
+		pvOut = (void *)((char *)pvInt + (uintptr_t)psBridgePackageKM->i32InBufferSize);
         if (psBridgePackageKM->i32InBufferSize > 0)
         {
             if (0 != ged_copy_from_user(pvInt, psBridgePackageKM->pvParamIn, psBridgePackageKM->i32InBufferSize))
@@ -111,39 +117,50 @@ static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM)
             }
         }
 
-        // we will change the below switch into a function pointer mapping table in the future
-        switch(GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID))
-        {
-        case GED_BRIDGE_COMMAND_LOG_BUF_GET:
-            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_get;
-            break;
-        case GED_BRIDGE_COMMAND_LOG_BUF_WRITE:
-            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_write;
-            break;
-        case GED_BRIDGE_COMMAND_LOG_BUF_RESET:
-            pFunc = (ged_bridge_func_type*)ged_bridge_log_buf_reset;
-            break;            
-        case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ:
-            pFunc = (ged_bridge_func_type*)ged_bridge_boost_gpu_freq;
-            break;
-        case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE:
-            pFunc = (ged_bridge_func_type*)ged_bridge_monitor_3D_fence;
-            break;
-        case GED_BRIDGE_COMMAND_QUERY_INFO:
-            pFunc = (ged_bridge_func_type*)ged_bridge_query_info;
-            break;            
-        case GED_BRIDGE_COMMAND_NOTIFY_VSYNC:
-            pFunc = (ged_bridge_func_type*)ged_bridge_notify_vsync;
-            break;
-        case GED_BRIDGE_COMMAND_DVFS_PROBE:
-            pFunc = (ged_bridge_func_type*)ged_bridge_dvfs_probe;
-            break;
-        case GED_BRIDGE_COMMAND_DVFS_UM_RETURN:
-            pFunc = (ged_bridge_func_type*)ged_bridge_dvfs_um_retrun;
-            break;
-			case GED_BRIDGE_COMMAND_EVENT_NOTIFY:
-				pFunc = (ged_bridge_func_type*)ged_bridge_event_notify;
-				break;
+		/* Make sure that the UM will never break the KM.
+		 * Check IO size are both matched the size of IO sturct.
+		 */
+#define SET_FUNC_AND_CHECK(func, struct_name) do { \
+	pFunc = (ged_bridge_func_type *) func; \
+	if (sizeof(GED_BRIDGE_IN_##struct_name) > psBridgePackageKM->i32InBufferSize || \
+			sizeof(GED_BRIDGE_OUT_##struct_name) > psBridgePackageKM->i32OutBufferSize) { \
+		GED_LOGE("GED_BRIDGE_COMMAND_##cmd fail io_size:%d/%d, expected: %zu/%zu", \
+				psBridgePackageKM->i32InBufferSize, psBridgePackageKM->i32OutBufferSize, \
+				sizeof(GED_BRIDGE_IN_##struct_name), sizeof(GED_BRIDGE_OUT_##struct_name)); \
+		goto dispatch_exit; \
+	} } while (0)
+
+	switch (GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID)) {
+	case GED_BRIDGE_COMMAND_LOG_BUF_GET:
+		SET_FUNC_AND_CHECK(ged_bridge_log_buf_get, LOGBUFGET);
+		break;
+	case GED_BRIDGE_COMMAND_LOG_BUF_WRITE:
+		SET_FUNC_AND_CHECK(ged_bridge_log_buf_write, LOGBUFWRITE);
+		break;
+	case GED_BRIDGE_COMMAND_LOG_BUF_RESET:
+		SET_FUNC_AND_CHECK(ged_bridge_log_buf_reset, LOGBUFRESET);
+		break;
+	case GED_BRIDGE_COMMAND_BOOST_GPU_FREQ:
+		SET_FUNC_AND_CHECK(ged_bridge_boost_gpu_freq, BOOSTGPUFREQ);
+		break;
+	case GED_BRIDGE_COMMAND_MONITOR_3D_FENCE:
+		SET_FUNC_AND_CHECK(ged_bridge_monitor_3D_fence, MONITOR3DFENCE);
+		break;
+	case GED_BRIDGE_COMMAND_QUERY_INFO:
+		SET_FUNC_AND_CHECK(ged_bridge_query_info, QUERY_INFO);
+		break;
+	case GED_BRIDGE_COMMAND_NOTIFY_VSYNC:
+		SET_FUNC_AND_CHECK(ged_bridge_notify_vsync, NOTIFY_VSYNC);
+		break;
+	case GED_BRIDGE_COMMAND_DVFS_PROBE:
+		SET_FUNC_AND_CHECK(ged_bridge_dvfs_probe, DVFS_PROBE);
+		break;
+	case GED_BRIDGE_COMMAND_DVFS_UM_RETURN:
+		SET_FUNC_AND_CHECK(ged_bridge_dvfs_um_retrun, DVFS_UM_RETURN);
+		break;
+	case GED_BRIDGE_COMMAND_EVENT_NOTIFY:
+		SET_FUNC_AND_CHECK(ged_bridge_event_notify, EVENT_NOTIFY);
+		break;
         default:
             GED_LOGE("Unknown Bridge ID: %u\n", GED_GET_BRIDGE_ID(psBridgePackageKM->ui32FunctionID));
             break;
@@ -163,7 +180,8 @@ static long ged_dispatch(GED_BRIDGE_PACKAGE *psBridgePackageKM)
         }
     }
 
-    return ret;
+dispatch_exit:
+	return ret;
 }
 
 DEFINE_SEMAPHORE(ged_dal_sem);

+ 14 - 1
drivers/misc/mediatek/include/mt-plat/battery_meter.h

@@ -142,6 +142,8 @@ struct battery_meter_custom_data {
 struct battery_meter_custom_data {
 
 	/* cust_battery_meter.h */
+	int cust_data_size;
+	int daemon_cmd_num;
 	int soc_flow;
 
 	int hw_fg_force_use_sw_ocv;
@@ -191,6 +193,8 @@ struct battery_meter_custom_data {
 	int difference_hwocv_rtc;
 	int difference_hwocv_swocv;
 	int difference_swocv_rtc;
+	int difference_vbat_rtc;
+	int difference_swocv_rtc_pos;
 	int max_swocv;
 
 	int max_hwocv;
@@ -226,9 +230,14 @@ struct battery_meter_custom_data {
 
 	int min_charging_smooth_time;
 
+	int embedded_battery;
+
 	/* SW Fuel gauge */
 	int apsleep_battery_voltage_compensate;
-
+	int max_smooth_time;
+	int smooth_uisoc2;
+	int trk_point_en;
+	int trk_point_thr;
 
 };
 
@@ -299,6 +308,7 @@ typedef enum {
 	FG_DAEMON_CMD_GET_SUSPEND_TIME,
 	FG_DAEMON_CMD_GET_SUSPEND_CAR,
 	FG_DAEMON_CMD_IS_HW_OCV_UPDATE,
+	FG_DAEMON_CMD_PRINT_LOG,
 
 	FG_DAEMON_CMD_FROM_USER_NUMBER
 } FG_DAEMON_CTRL_CMD_FROM_USER;
@@ -384,9 +394,12 @@ extern void fgauge_algo_run_get_init_data(void);
 extern void battery_meter_set_init_flag(kal_bool flag);
 extern void battery_meter_reset_sleep_time(void);
 extern int battery_meter_get_low_battery_interrupt_status(void);
+extern void mt_battery_set_init_vol(int);
 
 #if defined(CONFIG_MTK_HAFG_20)
 unsigned int get_cv_voltage(void);
 #endif
 
+extern void battery_meter_set_fg_int(void);
+
 #endif /* #ifndef _BATTERY_METER_H */

+ 2 - 1
drivers/misc/mediatek/include/mt-plat/battery_meter_hal.h

@@ -94,6 +94,7 @@ typedef enum {
 	BATTERY_METER_CMD_SET_LOW_BAT_INTERRUPT,
 	BATTERY_METER_CMD_GET_LOW_BAT_INTERRUPT_STATUS,
 	BATTERY_METER_CMD_GET_REFRESH_HW_OCV,
+	BATTERY_METER_CMD_GET_IS_HW_OCV_READY,
 
 	BATTERY_METER_CMD_NUMBER
 } BATTERY_METER_CTRL_CMD;
@@ -125,6 +126,6 @@ extern int Enable_FGADC_LOG;
 /* External function */
 /* ============================================================ */
 extern signed int bm_ctrl_cmd(BATTERY_METER_CTRL_CMD cmd, void *data);
-
+extern signed int pmic_is_battery_plugout(void);
 
 #endif				/* #ifndef _BATTERY_METER_HAL_H */

+ 34 - 0
drivers/misc/mediatek/include/mt-plat/mt6735/include/mach/mt_battery_meter.h

@@ -1,3 +1,16 @@
+/*
+ * Copyright (C) 2015 MediaTek Inc.
+ *
+ * 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.
+ *
+ * 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.
+ */
+
 #ifndef _CUST_BATTERY_METER_H
 #define _CUST_BATTERY_METER_H
 
@@ -83,6 +96,8 @@
 #define DIFFERENCE_HWOCV_RTC		30
 #define DIFFERENCE_HWOCV_SWOCV		10
 #define DIFFERENCE_SWOCV_RTC		10
+#define DIFFERENCE_VBAT_RTC 30
+#define DIFFERENCE_SWOCV_RTC_POS 15
 #define MAX_SWOCV			3
 
 #define DIFFERENCE_VOLTAGE_UPDATE	20
@@ -139,6 +154,13 @@
 #define FG_BAT_INT
 #define IS_BATTERY_REMOVE_BY_PMIC
 
+/*#define MAX_SMOOTHTIME*/
+/*#define SMOOTH_UISOC2*/
+/*#define LOW_BAT_SPM_TIMER_WAKEUP*/
+
+#define TRK_POINT_EN 0
+#define TRK_POINT_THR 5
+
 #elif defined(CONFIG_ARCH_MT6735M)
 /* ============================================================
 // define
@@ -267,6 +289,12 @@
 #define FG_BAT_INT
 #define IS_BATTERY_REMOVE_BY_PMIC
 
+/*#define MAX_SMOOTHTIME*/
+/*#define SMOOTH_UISOC2*/
+/*#define LOW_BAT_SPM_TIMER_WAKEUP*/
+
+#define TRK_POINT_EN 0
+#define TRK_POINT_THR 5
 
 
 #elif defined(CONFIG_ARCH_MT6753)
@@ -397,6 +425,12 @@
 #define FG_BAT_INT
 #define IS_BATTERY_REMOVE_BY_PMIC
 
+/*#define MAX_SMOOTHTIME*/
+/*#define SMOOTH_UISOC2*/
+/*#define LOW_BAT_SPM_TIMER_WAKEUP*/
+
+#define TRK_POINT_EN 0
+#define TRK_POINT_THR 5
 #endif
 
 #endif	/*#ifndef _CUST_BATTERY_METER_H*/

+ 2 - 0
drivers/misc/mediatek/include/mt-plat/mt6735/include/mach/upmu_sw.h

@@ -3,6 +3,7 @@
 
 #define AUXADC_SUPPORT_IMM_CURRENT_MODE
 #define BATTERY_DTS_SUPPORT
+#define INIT_BAT_CUR_FROM_PTIM
 
 #define BATTERY_CDP_WORKAROUND
 
@@ -172,6 +173,7 @@ extern void register_dlpt_notify(void (*dlpt_callback)(unsigned int), DLPT_PRIO
 
 
 
+extern int do_ptim_ex(bool isSuspend, unsigned int *bat, signed int *cur);
 
 
 #endif				/* _MT_PMIC_UPMU_SW_H_ */

+ 69 - 0
drivers/misc/mediatek/power/mt6735/battery_meter_hal.c

@@ -1,3 +1,16 @@
+/*
+ * Copyright (C) 2015 MediaTek Inc.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
 
 #include <linux/delay.h>
 #include <asm/div64.h>
@@ -8,6 +21,7 @@
 #include <mach/mt_battery_meter.h>
 #include <mach/mt_pmic.h>
 #include <mt-plat/battery_meter.h>
+#include <mt-plat/mt_boot_reason.h>
 
 
 /* ============================================================ // */
@@ -925,6 +939,29 @@ static signed int read_hw_ocv(void *data)
 	return STATUS_OK;
 }
 
+static signed int read_is_hw_ocv_ready(void *data)
+{
+#if defined(CONFIG_POWER_EXT)
+	*(signed int *) (data) = 0;
+#else
+#if defined(SWCHR_POWER_PATH)
+	*(signed int *) (data) = pmic_get_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_SWCHR);
+	bm_err("[read_is_hw_ocv_ready] is_hw_ocv_ready(SWCHR) %d\n", *(signed int *) (data));
+	pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 1);
+	mdelay(1);
+	pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 0);
+#else
+	*(signed int *) (data) = pmic_get_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_PCHR);
+	bm_err("[read_is_hw_ocv_ready] is_hw_ocv_ready(PCHR) %d\n", *(signed int *) (data));
+	pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 1);
+	mdelay(1);
+	pmic_set_register_value(PMIC_AUXADC_ADC_RDY_WAKEUP_CLR, 0);
+#endif
+#endif
+
+	return STATUS_OK;
+}
+
 static signed int dump_register_fgadc(void *data)
 {
 	return STATUS_OK;
@@ -960,6 +997,7 @@ signed int bm_ctrl_cmd(BATTERY_METER_CTRL_CMD cmd, void *data)
 		bm_func[BATTERY_METER_CMD_SET_COLUMB_INTERRUPT] = fgauge_set_columb_interrupt;
 		bm_func[BATTERY_METER_CMD_GET_BATTERY_PLUG_STATUS] = read_battery_plug_out_status;
 		bm_func[BATTERY_METER_CMD_GET_HW_FG_CAR_ACT] = fgauge_read_columb_accurate;
+		bm_func[BATTERY_METER_CMD_GET_IS_HW_OCV_READY] = read_is_hw_ocv_ready;
 	}
 
 	if (cmd < BATTERY_METER_CMD_NUMBER) {
@@ -970,3 +1008,34 @@ signed int bm_ctrl_cmd(BATTERY_METER_CTRL_CMD cmd, void *data)
 
 	return status;
 }
+
+signed int pmic_is_battery_plugout(void)
+{
+	int is_battery_plugout;
+	int pmic_strup_pwroff_seq_en = pmic_get_register_value(PMIC_STRUP_PWROFF_SEQ_EN);
+	int uvlo_rstb_status = pmic_get_register_value(PMIC_UVLO_RSTB_STATUS);
+	int is_long_press = (get_boot_reason() == BR_POWER_KEY ? 1 : 0);
+	int is_wdt_reboot = pmic_get_register_value(PMIC_WDTRSTB_STATUS);
+
+	pmic_set_register_value(PMIC_UVLO_RSTB_STATUS, 1);
+
+	if (pmic_strup_pwroff_seq_en) {
+		if (uvlo_rstb_status)
+			is_battery_plugout = 0;
+		else {
+			if (is_long_press)
+				is_battery_plugout = 0;
+			else {
+				if (is_wdt_reboot)
+					is_battery_plugout = 0;
+				else
+					is_battery_plugout = 1;
+			}
+		}
+	} else
+		is_battery_plugout = 1;
+
+	bm_err("[pmic_is_battery_plugout] [%d] %d, %d, %d, %d\n",
+		is_battery_plugout, pmic_strup_pwroff_seq_en, uvlo_rstb_status, is_long_press, is_wdt_reboot);
+	return is_battery_plugout;
+}

+ 56 - 8
drivers/misc/mediatek/power/mt6735/pmic.c

@@ -2283,15 +2283,15 @@ unsigned int ptim_cnt = 0;
 signed int count_time_out_adc_imp = 36;
 unsigned int count_adc_imp = 0;
 
-int do_ptim(bool isSuspend)
+
+int do_ptim_internal(bool isSuspend, unsigned int *bat, signed int *cur)
 {
 	unsigned int vbat_reg;
 	int ret = 0;
 
 	count_adc_imp = 0;
 	/*PMICLOG("[do_ptim] start\n"); */
-	if (isSuspend == false)
-		pmic_auxadc_lock();
+
 	/*pmic_set_register_value(PMIC_RG_AUXADC_RST,1); */
 	/*pmic_set_register_value(PMIC_RG_AUXADC_RST,0); */
 
@@ -2314,7 +2314,11 @@ int do_ptim(bool isSuspend)
 	/*set issue interrupt */
 	/*pmic_set_register_value(PMIC_RG_INT_EN_AUXADC_IMP,1); */
 
+#if defined(SWCHR_POWER_PATH)
+	pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CHSEL, 1);
+#else
 	pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CHSEL, 0);
+#endif
 	pmic_set_register_value(PMIC_AUXADC_IMP_AUTORPT_EN, 1);
 	pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_CNT, 3);
 	pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_MODE, 1);
@@ -2344,9 +2348,6 @@ PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN));*/
 	pmic_set_register_value(PMIC_AUXADC_CLR_IMP_CNT_STOP, 0);
 	pmic_set_register_value(PMIC_AUXADC_IMPEDANCE_IRQ_CLR, 0);
 
-
-	if (isSuspend == false)
-		pmic_auxadc_unlock();
 	/*PMICLOG("[do_ptim2] 0xee8=0x%x  0x2c6=0x%x\n", upmu_get_reg_value
 	   (0xee8),upmu_get_reg_value(0x2c6)); */
 
@@ -2356,13 +2357,60 @@ PMIC_RG_AUXADC_SMPS_CK_PDN_HWEN));*/
 
 
 	vbat_reg = pmic_get_register_value(PMIC_AUXADC_ADC_OUT_IMP_AVG);
-	ptim_bat_vol = (vbat_reg * 3 * 18000) / 32768;
+	/*ptim_bat_vol = (vbat_reg * 3 * 18000) / 32768;*/
+	*bat = (vbat_reg * 3 * 18000) / 32768;
+
+#if defined(CONFIG_MTK_SMART_BATTERY)
+	fgauge_read_IM_current((void *)cur);
+#else
+	*cur = 0;
+#endif
+	pr_err("do_ptim_internal : bat %d cur %d\n", *bat, *cur);
+
+#if defined(SWCHR_POWER_PATH)
+	pr_err("do_ptim_internal test: bat %d cur %d\n", *bat, *cur);
+#endif
+
+
+
+	return ret;
+}
 
-	fgauge_read_IM_current((void *)&ptim_R_curr);
+int do_ptim(bool isSuspend)
+{
+	int ret;
+
+	if (isSuspend == false)
+		pmic_auxadc_lock();
 
+	ret = do_ptim_internal(isSuspend, &ptim_bat_vol, &ptim_R_curr);
+
+	if (isSuspend == false)
+		pmic_auxadc_unlock();
 	return ret;
 }
 
+int do_ptim_ex(bool isSuspend, unsigned int *bat, signed int *cur)
+{
+	int ret;
+
+	if (isSuspend == false)
+		pmic_auxadc_lock();
+
+	ret = do_ptim_internal(isSuspend, bat, cur);
+
+	if (isSuspend == false)
+		pmic_auxadc_unlock();
+	return ret;
+}
+
+void get_ptim_value(unsigned int *bat, signed int *cur)
+{
+	pmic_auxadc_lock();
+	*bat = ptim_bat_vol;
+	*cur = ptim_R_curr;
+	pmic_auxadc_unlock();
+}
 
 void enable_dummy_load(unsigned int en)
 {

+ 34 - 18
drivers/misc/mediatek/teei/V1.0/teei_fp/fp_func.c

@@ -19,7 +19,10 @@
 
 #include "teei_fp.h"
 
-#define FP_SIZE	0x80000
+#define MICROTRUST_FP_SIZE	(0x80000)
+#define FP_BUFFER_OFFSET	(0x10)
+#define FP_LEN_MAX		(MICROTRUST_FP_SIZE - FP_BUFFER_OFFSET)
+#define FP_LEN_MIN		0
 #define CMD_MEM_CLEAR	_IO(0x775A777E, 0x1)
 #define CMD_FP_CMD      _IO(0x775A777E, 0x2)
 #define FP_MAJOR	254
@@ -33,7 +36,7 @@ static dev_t devno;
 struct semaphore fp_api_lock;
 struct fp_dev {
 	struct cdev cdev;
-	unsigned char mem[FP_SIZE];
+	unsigned char mem[MICROTRUST_FP_SIZE];
 	struct semaphore sem;
 };
 
@@ -69,6 +72,9 @@ static int fp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 	unsigned int args_len = 0;
 	unsigned int fp_cid = 0xFF;
 	unsigned int fp_fid = 0xFF;
+	unsigned char args[16] = {0};
+	unsigned int buff_len = 0;
+
 #ifdef FP_DEBUG
 	printk("##################################\n");
 	printk("fp ioctl received received cmd is: %x arg is %x\n", cmd, (unsigned int)arg);
@@ -76,36 +82,47 @@ static int fp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 #endif
 	switch (cmd) {
 	case CMD_MEM_CLEAR:
-		printk(KERN_INFO "CMD MEM CLEAR. \n");
+		pr_err("CMD MEM CLEAR.\n");
 		break;
 	case CMD_FP_CMD:
+		if (copy_from_user((void *)args, (void *)arg, FP_BUFFER_OFFSET)) {
+			pr_err("copy args from user failed.\n");
+			up(&fp_api_lock);
+			return -EFAULT;
+		}
 		/*TODO compute args length*/
 		/*[11-15] is the length of data*/
-		args_len = *((unsigned int *)(arg + 12));
+		args_len = *((unsigned int *)(args + 12));
+		if (args_len > FP_LEN_MAX || (args_len <= FP_LEN_MIN)) {
+			pr_err("args_len is invalid %d !\n", args_len);
+			up(&fp_api_lock);
+			return -EFAULT;
+		}
+		buff_len = args_len + FP_BUFFER_OFFSET;
 		/*[0-3] is cmd id*/
-		fp_cid = *((unsigned int *)(arg));
+		fp_cid = *((unsigned int *)(args));
 		/*[4-7] is fuction id*/
-		fp_fid = *((unsigned int *)(arg + 4));
+		fp_fid = *((unsigned int *)(args + 4));
 #ifdef FP_DEBUG
-		printk("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
-		printk("invoke fp cmd CMD_FP_CMD: arg's address is %x, args's length %d\n", (unsigned int)arg, args_len);
-		printk("invoke fp cmd fp_cid is %d fp_fid is %d \n", fp_cid, fp_fid);
+		pr_debug("invoke fp cmd CMD_FP_CMD: arg's address is %x, args's length %d\n",
+			(unsigned int)arg, args_len);
+		pr_debug("invoke fp cmd fp_cid is %d fp_fid is %d\n", fp_cid, fp_fid);
 #endif
 		if (!fp_buff_addr) {
-			printk("fp_buiff_addr is invalid!. \n");
+			pr_err("fp_buiff_addr is invalid!.\n");
 			up(&fp_api_lock);
 			return -EFAULT;
 		}
-		memset((void *)fp_buff_addr, 0, args_len + 16);
-		if (copy_from_user((void *)fp_buff_addr, (void *)arg,
-				args_len + 16)) {
-			printk(KERN_INFO "copy from user failed. \n");
+		memset((void *)fp_buff_addr, 0, buff_len);
+
+		if (copy_from_user((void *)fp_buff_addr, (void *)arg, buff_len)) {
+			pr_err("copy from user failed.\n");
 			up(&fp_api_lock);
 			return -EFAULT;
 		}
 
 		Flush_Dcache_By_Area((unsigned long)fp_buff_addr,
-				fp_buff_addr + FP_SIZE);
+				fp_buff_addr + MICROTRUST_FP_SIZE);
 		/*send command data to TEEI*/
 		send_fp_command(FP_DRIVER_ID);
 #ifdef FP_DEBUG
@@ -114,9 +131,8 @@ static int fp_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 		printk("[%s][%d] fp_buff_addr 88 - 91 = %d\n", __func__, args_len, *((unsigned int *)(fp_buff_addr + 88)));
 #endif
 
-		if (copy_to_user((void *)arg, (unsigned long)fp_buff_addr,
-				args_len + 16)) {
-			printk("copy from user failed. \n");
+		if (copy_to_user((void *)arg, (void *)fp_buff_addr, buff_len)) {
+			pr_err("copy from user failed.\n");
 			up(&fp_api_lock);
 			return -EFAULT;
 		}

+ 13 - 2
drivers/misc/mediatek/video/common/fbconfig_kdebug.c

@@ -97,6 +97,7 @@ static PM_TOOL_T pm_params = {
 	.pLcm_params = NULL,
 	.pLcm_drv = NULL,
 };
+struct mutex fb_config_lock;
 
 static void *pm_get_handle(void)
 {
@@ -141,7 +142,7 @@ void Panel_Master_DDIC_config(void)
 
 	struct list_head *p;
 	CONFIG_RECORD_LIST *node;
-
+	mutex_lock(&fb_config_lock);
 	list_for_each_prev(p, &head_list.list) {
 		node = list_entry(p, CONFIG_RECORD_LIST, list);
 		switch (node->record.type) {
@@ -159,6 +160,7 @@ void Panel_Master_DDIC_config(void)
 		}
 
 	}
+	mutex_unlock(&fb_config_lock);
 
 }
 
@@ -184,7 +186,7 @@ static void free_list_memory(void)
 {
 	struct list_head *p, *n;
 	CONFIG_RECORD_LIST *print;
-
+	mutex_lock(&fb_config_lock);
 	list_for_each_safe(p, n, &head_list.list) {
 		print = list_entry(p, CONFIG_RECORD_LIST, list);
 		list_del(&print->list);
@@ -195,6 +197,7 @@ static void free_list_memory(void)
 		pr_debug("*****list is empty!!\n");
 	else
 		pr_debug("*****list is NOT empty!!\n");
+	mutex_unlock(&fb_config_lock);
 
 }
 
@@ -292,16 +295,23 @@ static long fbconfig_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 			record_tmp_list = NULL;
 			return -EFAULT;
 		}
+		mutex_lock(&fb_config_lock);
 		list_add(&record_tmp_list->list, &head_list.list);
+		mutex_unlock(&fb_config_lock);
 		return 0;
+
+
 	}
 	case DRIVER_IC_CONFIG_DONE:
 	{
+
 		/* print_from_head_to_tail(); */
+		/* while all DRIVER_IC_CONFIG is added, use this to set complete */
 		Panel_Master_dsi_config_entry("PM_DDIC_CONFIG", NULL);
 		/*free the memory ..... */
 		free_list_memory();
 		return 0;
+
 	}
 	case MIPI_SET_CC:
 	{
@@ -1255,6 +1265,7 @@ void PanelMaster_Init(void)
 					       S_IFREG | S_IRUGO, NULL, (void *)0, &fbconfig_fops);
 
 	INIT_LIST_HEAD(&head_list.list);
+	mutex_init(&fb_config_lock);
 }
 
 void PanelMaster_Deinit(void)

+ 5 - 5
drivers/power/mediatek/battery_common.c

@@ -86,8 +86,6 @@
 /* Battery Logging Entry */
 /* ////////////////////////////////////////////////////////////////////////////// */
 int Enable_BATDRV_LOG = BAT_LOG_CRTI;
-/* static struct proc_dir_entry *proc_entry; */
-char proc_bat_data[32];
 
 /* ///////////////////////////////////////////////////////////////////////////////////////// */
 /* // Smart Battery Structure */
@@ -462,15 +460,17 @@ EXPORT_SYMBOL(wake_up_bat3);
 
 static ssize_t bat_log_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
 {
-	if (copy_from_user(&proc_bat_data, buff, len)) {
+	char proc_bat_data;
+
+	if ((len <= 0) || copy_from_user(&proc_bat_data, buff, 1)) {
 		battery_log(BAT_LOG_FULL, "bat_log_write error.\n");
 		return -EFAULT;
 	}
 
-	if (proc_bat_data[0] == '1') {
+	if (proc_bat_data == '1') {
 		battery_log(BAT_LOG_CRTI, "enable battery driver log system\n");
 		Enable_BATDRV_LOG = 1;
-	} else if (proc_bat_data[0] == '2') {
+	} else if (proc_bat_data == '2') {
 		battery_log(BAT_LOG_CRTI, "enable battery driver log system:2\n");
 		Enable_BATDRV_LOG = 2;
 	} else {

+ 40 - 11
drivers/power/mediatek/battery_common_fg_20.c

@@ -96,8 +96,6 @@ extern unsigned char AW2015_LED_RED_OFF(void);
 /* Battery Logging Entry */
 /* ////////////////////////////////////////////////////////////////////////////// */
 int Enable_BATDRV_LOG = BAT_LOG_CRTI;
-/* static struct proc_dir_entry *proc_entry; */
-char proc_bat_data[32];
 
 /* ///////////////////////////////////////////////////////////////////////////////////////// */
 /* // Smart Battery Structure */
@@ -481,15 +479,17 @@ EXPORT_SYMBOL(wake_up_bat3);
 
 static ssize_t bat_log_write(struct file *filp, const char __user *buff, size_t len, loff_t *data)
 {
-	if (copy_from_user(&proc_bat_data, buff, len)) {
+	char proc_bat_data;
+
+	if ((len <= 0) || copy_from_user(&proc_bat_data, buff, 1)) {
 		battery_log(BAT_LOG_FULL, "bat_log_write error.\n");
 		return -EFAULT;
 	}
 
-	if (proc_bat_data[0] == '1') {
+	if (proc_bat_data == '1') {
 		battery_log(BAT_LOG_CRTI, "enable battery driver log system\n");
 		Enable_BATDRV_LOG = 1;
-	} else if (proc_bat_data[0] == '2') {
+	} else if (proc_bat_data == '2') {
 		battery_log(BAT_LOG_CRTI, "enable battery driver log system:2\n");
 		Enable_BATDRV_LOG = 2;
 	} else {
@@ -740,6 +740,11 @@ static struct battery_data battery_main = {
 #endif
 };
 
+void mt_battery_set_init_vol(int init_voltage)
+{
+	BMT_status.bat_vol = init_voltage;
+	battery_main.BAT_batt_vol = init_voltage;
+}
 
 #if !defined(CONFIG_POWER_EXT)
 /* ///////////////////////////////////////////////////////////////////////////////////////// */
@@ -1711,12 +1716,13 @@ static void battery_update(struct battery_data *bat_data)
 
 		if (dlpt_check_power_off() == 1) {
 			bat_data->BAT_CAPACITY = 0;
+			BMT_status.UI_SOC2 = 0;
 			cnt++;
 			battery_log(BAT_LOG_CRTI,
 				    "[DLPT_POWER_OFF_EN] SOC=%d to power off , cnt=%d\n",
 				    bat_data->BAT_CAPACITY, cnt);
 
-			if (cnt >= 2)
+			if (cnt >= 4)
 				kernel_restart("DLPT reboot system");
 
 		} else {
@@ -1746,6 +1752,7 @@ void update_charger_info(int wireless_state)
 
 static void wireless_update(struct wireless_data *wireless_data)
 {
+	static int wireless_status = -1;
 	struct power_supply *wireless_psy = &wireless_data->psy;
 
 	if (BMT_status.charger_exist == KAL_TRUE || g_wireless_state) {
@@ -1759,11 +1766,15 @@ static void wireless_update(struct wireless_data *wireless_data)
 		wireless_data->WIRELESS_ONLINE = 0;
 	}
 
-	power_supply_changed(wireless_psy);
+	if (wireless_status != wireless_data->WIRELESS_ONLINE) {
+		wireless_status = wireless_data->WIRELESS_ONLINE;
+		power_supply_changed(wireless_psy);
+	}
 }
 
 static void ac_update(struct ac_data *ac_data)
 {
+	static int ac_status = -1;
 	struct power_supply *ac_psy = &ac_data->psy;
 
 	if (BMT_status.charger_exist == KAL_TRUE) {
@@ -1790,11 +1801,15 @@ static void ac_update(struct ac_data *ac_data)
 		ac_data->AC_ONLINE = 0;
 	}
 
-	power_supply_changed(ac_psy);
+	if (ac_status != ac_data->AC_ONLINE) {
+		ac_status = ac_data->AC_ONLINE;
+		power_supply_changed(ac_psy);
+	}
 }
 
 static void usb_update(struct usb_data *usb_data)
 {
+	static int usb_status = -1;
 	struct power_supply *usb_psy = &usb_data->psy;
 
 	if (BMT_status.charger_exist == KAL_TRUE) {
@@ -1809,7 +1824,10 @@ static void usb_update(struct usb_data *usb_data)
 		usb_data->USB_ONLINE = 0;
 	}
 
-	power_supply_changed(usb_psy);
+	if (usb_status != usb_data->USB_ONLINE) {
+		usb_status = usb_data->USB_ONLINE;
+		power_supply_changed(usb_psy);
+	}
 }
 
 #endif
@@ -1859,6 +1877,12 @@ kal_bool bat_is_charging_full(void)
 
 unsigned int bat_get_ui_percentage(void)
 {
+	if ((g_platform_boot_mode == META_BOOT) ||
+		(g_platform_boot_mode == ADVMETA_BOOT) ||
+		(g_platform_boot_mode == FACTORY_BOOT) ||
+		(g_platform_boot_mode == ATE_FACTORY_BOOT))
+		return 75;
+
 	return BMT_status.UI_SOC2;
 }
 
@@ -2103,9 +2127,10 @@ void mt_battery_GetBatteryData(void)
 		batteryIndex = 0;
 
 	battery_log(BAT_LOG_CRTI,
-		    "[kernel]AvgVbat %d,bat_vol %d, AvgI %d, I %d, VChr %d, AvgT %d, T %d, ZCV %d\n",
+		    "[kernel]AvgVbat %d,bat_vol %d, AvgI %d, I %d, VChr %d, AvgT %d, T %d, ZCV %d, CHR_Type %d, SOC %3d:%3d:%3d\n",
 		    BMT_status.bat_vol, bat_vol, BMT_status.ICharging, ICharging,
-		    BMT_status.charger_vol, BMT_status.temperature, temperature, BMT_status.ZCV);
+		    BMT_status.charger_vol, BMT_status.temperature, temperature, BMT_status.ZCV,
+		    BMT_status.charger_type, BMT_status.SOC, BMT_status.UI_SOC, BMT_status.UI_SOC2);
 }
 
 
@@ -2846,6 +2871,7 @@ void BAT_thread(void)
 		mt_battery_charging_algorithm();
 	}
 	mt_kpoc_power_off_check();
+	battery_meter_set_fg_int();
 }
 
 /* ///////////////////////////////////////////////////////////////////////////////////////// */
@@ -2912,6 +2938,9 @@ int bat_update_thread(void *x)
 	/* Run on a process content */
 	while (1) {
 		mutex_lock(&bat_update_mutex);
+#ifdef USING_SMOOTH_UI_SOC2
+		battery_meter_smooth_uisoc2();
+#endif
 		mt_battery_update_status();
 		mutex_unlock(&bat_update_mutex);
 

+ 16 - 10
drivers/power/mediatek/battery_meter.c

@@ -56,9 +56,6 @@ int Enable_FGADC_LOG = 0;
 /* ============================================================ // */
 BATTERY_METER_CONTROL battery_meter_ctrl = NULL;
 
-/* static struct proc_dir_entry *proc_entry_fgadc; */
-static char proc_fgadc_data[32];
-
 kal_bool gFG_Is_Charging = KAL_FALSE;
 signed int g_auxadc_solution = 0;
 unsigned int g_spm_timer = 600;
@@ -3051,6 +3048,7 @@ void fgauge_algo_run_init(void)
 unsigned char reset_fg_bat_int = KAL_TRUE;
 void fg_bat_int_handler(void)
 {
+	bm_print(BM_LOG_CRTI, "[fg_bat_int_handler] Detect\n");
 	reset_fg_bat_int = KAL_TRUE;
 	wake_up_bat2();
 }
@@ -3109,8 +3107,9 @@ void fgauge_initialization(void)
 		 gFG_voltage, gFG_current, gFG_columb, gFG_temp, gFG_capacity, gFG_BATT_CAPACITY);
 
 #if defined(FG_BAT_INT)
-	/*pmic_register_interrupt_callback(41, fg_bat_int_handler);*/
-	/*pmic_register_interrupt_callback(40, fg_bat_int_handler);*/
+	pmic_register_interrupt_callback(41, fg_bat_int_handler);
+	pmic_register_interrupt_callback(40, fg_bat_int_handler);
+	bm_print(BM_LOG_CRTI, "[fgauge_initialization] fg_bat_int_handler register\n");
 #endif
 #endif
 }
@@ -3518,7 +3517,7 @@ signed int battery_meter_trans_battery_percentage(kal_bool d_val)
 #if defined(FG_BAT_INT)
 signed int battery_meter_set_columb_interrupt(unsigned int val)
 {
-	battery_log(BAT_LOG_FULL, "battery_meter_set_columb_interrupt=%d\n", val);
+	battery_log(BAT_LOG_CRTI, "battery_meter_set_columb_interrupt=%d\n", val);
 	battery_meter_ctrl(BATTERY_METER_CMD_SET_COLUMB_INTERRUPT, &val);
 	return 0;
 }
@@ -3793,15 +3792,17 @@ signed int battery_meter_get_VSense(void)
 static ssize_t fgadc_log_write(struct file *filp, const char __user *buff,
 			       size_t len, loff_t *data)
 {
-	if (copy_from_user(&proc_fgadc_data, buff, len)) {
+	char proc_fgadc_data;
+
+	if ((len <= 0) || copy_from_user(&proc_fgadc_data, buff, 1)) {
 		bm_print(BM_LOG_CRTI, "fgadc_log_write error.\n");
 		return -EFAULT;
 	}
 
-	if (proc_fgadc_data[0] == '1') {
+	if (proc_fgadc_data == '1') {
 		bm_print(BM_LOG_CRTI, "enable FGADC driver log system\n");
 		Enable_FGADC_LOG = BM_LOG_CRTI;
-	} else if (proc_fgadc_data[0] == '2') {
+	} else if (proc_fgadc_data == '2') {
 		bm_print(BM_LOG_CRTI, "enable FGADC driver log system:2\n");
 		Enable_FGADC_LOG = BM_LOG_FULL;
 	} else {
@@ -4440,6 +4441,8 @@ static int battery_meter_suspend(struct platform_device *dev, pm_message_t state
 	}
 #endif
 #endif				/* #if defined(FG_BAT_INT) */
+	bm_print(BM_LOG_CRTI, "[battery_meter_suspend] sleep time = %d,%ld %ld\n",
+	_g_bat_sleep_total_time, g_sleep_total_time.tv_sec, g_sleep_total_time.tv_nsec);
 
 	/* -- hibernation path */
 	if (state.event == PM_EVENT_FREEZE) {
@@ -4467,6 +4470,9 @@ static int battery_meter_suspend(struct platform_device *dev, pm_message_t state
 		battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_OCV, &g_hw_ocv_before_sleep);
 	}
 #endif
+	bm_print(BM_LOG_CRTI, "[battery_meter_suspend]2 sleep time = %d,%ld %ld\n", _g_bat_sleep_total_time,
+	g_sleep_total_time.tv_sec, g_sleep_total_time.tv_nsec);
+
 	bm_print(BM_LOG_CRTI, "[battery_meter_suspend]\n");
 	return 0;
 }
@@ -4727,7 +4733,7 @@ static int battery_meter_resume(struct platform_device *dev)
 #if defined(FG_BAT_INT)
 #if defined(CONFIG_POWER_EXT)
 #elif defined(SOC_BY_HW_FG)
-	battery_meter_set_columb_interrupt(0);
+	/*battery_meter_set_columb_interrupt(0);*/
 #endif
 #endif				/* #if defined(FG_BAT_INT) */
 

+ 144 - 24
drivers/power/mediatek/battery_meter_fg_20.c

@@ -69,9 +69,6 @@ int Enable_FGADC_LOG = BMLOG_INFO_LEVEL;
 /* ============================================================ // */
 BATTERY_METER_CONTROL battery_meter_ctrl = NULL;
 
-/* static struct proc_dir_entry *proc_entry_fgadc; */
-static char proc_fgadc_data[32];
-
 kal_bool gFG_Is_Charging = KAL_FALSE;
 kal_bool gFG_Is_Charging_init = KAL_FALSE;
 
@@ -149,6 +146,14 @@ int gFG_result_soc = 0;
 #define Q_MAX_SYS_VOLTAGE 3300
 #endif
 
+#ifndef DIFFERENCE_VBAT_RTC
+#define DIFFERENCE_VBAT_RTC 10
+#endif
+
+#ifndef DIFFERENCE_SWOCV_RTC_POS
+#define DIFFERENCE_SWOCV_RTC_POS 15
+#endif
+
 
 /* smooth time tracking */
 signed int gFG_coulomb_act_time = -1;
@@ -397,6 +402,9 @@ static signed int shutdown_gauge1_xmins;
 #define APSLEEP_BATTERY_VOLTAGE_COMPENSATE 150
 #endif
 
+#ifndef MAX_SMOOTH_TIME
+#define MAX_SMOOTH_TIME 1800
+#endif
 
 static signed int shutdown_gauge1_mins = SHUTDOWN_GAUGE1_MINS;
 
@@ -658,6 +666,9 @@ int __batt_meter_init_cust_data_from_cust_header(void)
 	batt_meter_cust_data.max_vbat = MAX_VBAT;
 	batt_meter_cust_data.difference_hwocv_vbat = DIFFERENCE_HWOCV_VBAT;
 
+	batt_meter_cust_data.difference_vbat_rtc = DIFFERENCE_VBAT_RTC;
+	batt_meter_cust_data.difference_swocv_rtc_pos = DIFFERENCE_SWOCV_RTC_POS;
+
 	batt_meter_cust_data.suspend_current_threshold = SUSPEND_CURRENT_CHECK_THRESHOLD;
 	batt_meter_cust_data.ocv_check_time = OCV_RECOVER_TIME;
 
@@ -710,6 +721,13 @@ int __batt_meter_init_cust_data_from_cust_header(void)
 #endif				/* #if defined(Q_MAX_BY_CURRENT) */
 	batt_meter_cust_data.q_max_sys_voltage = Q_MAX_SYS_VOLTAGE;
 
+#if defined(CONFIG_MTK_EMBEDDED_BATTERY)
+	batt_meter_cust_data.embedded_battery = 1;
+#else
+	batt_meter_cust_data.embedded_battery = 0;
+#endif
+
+
 #if defined(SHUTDOWN_GAUGE0)
 	batt_meter_cust_data.shutdown_gauge0 = 1;
 #else				/* #if defined(SHUTDOWN_GAUGE0) */
@@ -727,6 +745,16 @@ int __batt_meter_init_cust_data_from_cust_header(void)
 	batt_meter_cust_data.apsleep_battery_voltage_compensate =
 	    APSLEEP_BATTERY_VOLTAGE_COMPENSATE;
 
+#if defined(SMOOTH_UISOC2)
+	batt_meter_cust_data.smooth_uisoc2 = 1;
+#else
+	batt_meter_cust_data.smooth_uisoc2 = 0;
+#endif
+
+	batt_meter_cust_data.max_smooth_time = MAX_SMOOTH_TIME;
+	batt_meter_cust_data.trk_point_en = TRK_POINT_EN;
+	batt_meter_cust_data.trk_point_thr = TRK_POINT_THR;
+
 	return 0;
 }
 
@@ -1533,8 +1561,12 @@ void update_fg_dbg_tool_value(void)
 
 void fgauge_algo_run_get_init_data(void)
 {
-
+#if defined(INIT_BAT_CUR_FROM_PTIM)
+	unsigned int bat = 0;
+	signed int cur = 0;
+#else
 	int ret = 0;
+#endif
 	kal_bool charging_enable = KAL_FALSE;
 
 #if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) && !defined(SWCHR_POWER_PATH)
@@ -1545,14 +1577,25 @@ void fgauge_algo_run_get_init_data(void)
 
 	msleep(50);
 /* 1. Get Raw Data */
+#if defined(INIT_BAT_CUR_FROM_PTIM)
+	do_ptim_ex(true, &bat, &cur);
+	gFG_voltage_init = bat/10;
+	gFG_current_init = abs(cur);
+	if (cur > 0)
+		gFG_Is_Charging_init = KAL_FALSE;
+	else
+		gFG_Is_Charging_init = KAL_TRUE;
+#else
 	gFG_voltage_init = battery_meter_get_battery_voltage(KAL_TRUE);
 	ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT, &gFG_current_init);
 	ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CURRENT_SIGN, &gFG_Is_Charging_init);
+#endif
 	charging_enable = KAL_TRUE;
 	battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable);
 	bm_info
 	    ("1.[fgauge_algo_run_get_init_data](gFG_voltage_init %d, gFG_current_init %d, gFG_Is_Charging_init %d)\n",
 	     gFG_voltage_init, gFG_current_init, gFG_Is_Charging_init);
+	mt_battery_set_init_vol(gFG_voltage_init);
 }
 #endif
 
@@ -1653,6 +1696,9 @@ signed int get_dynamic_period(int first_use, int first_wakeup_time, int battery_
 
 	int ret = 0;
 	signed int car_instant = 0;
+	signed int vbat_val = 0;
+
+	vbat_val = g_sw_vbat_temp;
 
 	ret = battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT, &car_instant);
 
@@ -1661,6 +1707,16 @@ signed int get_dynamic_period(int first_use, int first_wakeup_time, int battery_
 	else
 		g_spm_timer = wake_up_smooth_time;
 
+#ifdef LOW_BAT_SPM_TIMER_WAKEUP
+	/* > 3.5v, 1min */
+	if ((vbat_val > VBAT_LOW_POWER_WAKEUP) && (vbat_val < VBAT_NORMAL_WAKEUP))
+		g_spm_timer = 60;
+
+	/* < 3.5v, 0.5 min */
+	if (vbat_val < VBAT_LOW_POWER_WAKEUP)
+		g_spm_timer = CLOSE_POWEROFF_WAKEUP_PERIOD;
+#endif
+
 	bm_print(BM_LOG_CRTI,
 		 "[get_dynamic_period] g_spm_timer:%d wake_up_smooth_time:%d vbat:%d car:%d\r\n",
 		 g_spm_timer, wake_up_smooth_time, g_sw_vbat_temp, car_instant);
@@ -2014,9 +2070,11 @@ signed int battery_meter_initial(void)
 		/* 1. HW initialization */
 		battery_meter_ctrl(BATTERY_METER_CMD_HW_FG_INIT, NULL);
 
+		fgauge_algo_run_get_init_data();
+
 		if (wakeup_fg_algo(FG_MAIN) == -1) {
 			/* fgauge_initialization(); */
-			fgauge_algo_run_get_init_data();
+			/* fgauge_algo_run_get_init_data(); */
 			bm_err("[battery_meter_initial] SOC_BY_HW_FG not done\n");
 		}
 #endif
@@ -2025,9 +2083,11 @@ signed int battery_meter_initial(void)
 		/* 1. HW initialization */
 		battery_meter_ctrl(BATTERY_METER_CMD_HW_FG_INIT, NULL);
 
+		fgauge_algo_run_get_init_data();
+
 		if (wakeup_fg_algo(FG_MAIN) == -1) {
 			/* fgauge_initialization(); */
-			fgauge_algo_run_get_init_data();
+			/* fgauge_algo_run_get_init_data(); */
 			bm_err("[battery_meter_initial] SOC_BY_SW_FG not done\n");
 		}
 #endif
@@ -2122,33 +2182,35 @@ signed int battery_meter_get_VSense(void)
 static ssize_t fgadc_log_write(struct file *filp, const char __user *buff,
 			       size_t len, loff_t *data)
 {
-	if (copy_from_user(&proc_fgadc_data, buff, len)) {
+	char proc_fgadc_data;
+
+	if ((len <= 0) || copy_from_user(&proc_fgadc_data, buff, 1)) {
 		bm_debug("fgadc_log_write error.\n");
 		return -EFAULT;
 	}
 
-	if (proc_fgadc_data[0] == '1') {
+	if (proc_fgadc_data == '1') {
 		bm_debug("enable FGADC driver log system\n");
 		Enable_FGADC_LOG = 1;
-	} else if (proc_fgadc_data[0] == '2') {
+	} else if (proc_fgadc_data == '2') {
 		bm_debug("enable FGADC driver log system:2\n");
 		Enable_FGADC_LOG = 2;
-	} else if (proc_fgadc_data[0] == '3') {
+	} else if (proc_fgadc_data == '3') {
 		bm_debug("enable FGADC driver log system:3\n");
 		Enable_FGADC_LOG = 3;
-	} else if (proc_fgadc_data[0] == '4') {
+	} else if (proc_fgadc_data == '4') {
 		bm_debug("enable FGADC driver log system:4\n");
 		Enable_FGADC_LOG = 4;
-	} else if (proc_fgadc_data[0] == '5') {
+	} else if (proc_fgadc_data == '5') {
 		bm_debug("enable FGADC driver log system:5\n");
 		Enable_FGADC_LOG = 5;
-	} else if (proc_fgadc_data[0] == '6') {
+	} else if (proc_fgadc_data == '6') {
 		bm_debug("enable FGADC driver log system:6\n");
 		Enable_FGADC_LOG = 6;
-	} else if (proc_fgadc_data[0] == '7') {
+	} else if (proc_fgadc_data == '7') {
 		bm_debug("enable FGADC driver log system:7\n");
 		Enable_FGADC_LOG = 7;
-	} else if (proc_fgadc_data[0] == '8') {
+	} else if (proc_fgadc_data == '8') {
 		bm_debug("enable FGADC driver log system:8\n");
 		Enable_FGADC_LOG = 8;
 	} else {
@@ -3111,13 +3173,43 @@ static ssize_t store_FG_daemon_disable(struct device *dev, struct device_attribu
 static DEVICE_ATTR(FG_daemon_disable, 0664, show_FG_daemon_disable, store_FG_daemon_disable);
 /* ------------------------------------------------------------------------------------------- */
 
+static ssize_t show_FG_drv_force25c(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	bm_debug("[FG] show FG_drv_force25c : %d\n", batt_meter_cust_data.fixed_tbat_25);
+	return sprintf(buf, "%d\n", batt_meter_cust_data.fixed_tbat_25);
+}
+
+static ssize_t store_FG_drv_force25c(struct device *dev, struct device_attribute *attr,
+					const char *buf, size_t size)
+{
+	unsigned long val = 0;
+	int ret;
+
+	bm_debug("[Enable FG_drv_force25c]\n");
+	batt_meter_cust_data.fixed_tbat_25 = 1;
+
+	if (buf != NULL && size != 0) {
+		bm_debug("[FG_drv_force25c] buf is %s\n", buf);
+		ret = kstrtoul(buf, 10, &val);
+		if (val < 0) {
+			bm_debug("[FG_drv_force25c] val is %d ??\n", (int)val);
+			val = 0;
+		}
+		batt_meter_cust_data.fixed_tbat_25 = val;
+		bm_debug("[FG_drv_force25c] fixed_tbat_25=%d, ret=%d\n", batt_meter_cust_data.fixed_tbat_25, ret);
+	}
+
+	return size;
+}
+
+static DEVICE_ATTR(FG_drv_force25c, 0664, show_FG_drv_force25c, store_FG_drv_force25c);
+/* ------------------------------------------------------------------------------------------- */
 #ifdef FG_BAT_INT
 unsigned char reset_fg_bat_int = KAL_TRUE;
 
 signed int fg_bat_int_coulomb_pre;
 signed int fg_bat_int_coulomb;
 
-
 void fg_bat_int_handler(void)
 {
 	battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT, &fg_bat_int_coulomb);
@@ -3125,12 +3217,11 @@ void fg_bat_int_handler(void)
 		    fg_bat_int_coulomb);
 
 	reset_fg_bat_int = KAL_TRUE;
-	if (bat_is_charger_exist() == KAL_FALSE) {
-		battery_log(BAT_LOG_CRTI, "wake up user space >>\n");
-		/* self_correct_dod_scheme(duration_time); */
-		wakeup_fg_algo(FG_RESUME);
-	}
 
+	battery_log(BAT_LOG_CRTI, "wake up user space >>\n");
+
+	wakeup_fg_algo(FG_MAIN);
+	battery_meter_set_fg_int();
 }
 
 signed int battery_meter_set_columb_interrupt(unsigned int val)
@@ -3139,14 +3230,31 @@ signed int battery_meter_set_columb_interrupt(unsigned int val)
 	battery_meter_ctrl(BATTERY_METER_CMD_SET_COLUMB_INTERRUPT, &val);
 	return 0;
 }
-
 #endif
 
+void battery_meter_set_fg_int(void)
+{
+#if defined(FG_BAT_INT)
+	battery_meter_ctrl(BATTERY_METER_CMD_GET_HW_FG_CAR_ACT, &fg_bat_int_coulomb_pre);
+	bm_notice("[battery_meter_set_fg_int]fg_bat_int_coulomb_pre %d 1p:%d\n",
+		fg_bat_int_coulomb_pre,
+		batt_meter_cust_data.q_max_pos_25/100);
+	if (reset_fg_bat_int == KAL_TRUE) {
+		battery_meter_set_columb_interrupt(batt_meter_cust_data.q_max_pos_25/100);
+		reset_fg_bat_int = KAL_FALSE;
+		battery_log(BAT_LOG_CRTI, "battery_meter_set_fg_int\n");
+	} else {
+		battery_log(BAT_LOG_CRTI, "not battery_meter_set_fg_int\n");
+	}
+#endif
+}
 
 static int battery_meter_probe(struct platform_device *dev)
 {
 	int ret_device_file = 0;
+#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)
 	char *temp_strptr;
+#endif
 
 	bm_info("[battery_meter_probe] probe\n");
 	/* select battery meter control method */
@@ -3210,6 +3318,7 @@ static int battery_meter_probe(struct platform_device *dev)
 #endif
 	ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_daemon_log_level);
 	ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_daemon_disable);
+	ret_device_file = device_create_file(&(dev->dev), &dev_attr_FG_drv_force25c);
 
 
 
@@ -3245,7 +3354,7 @@ static int battery_meter_suspend(struct platform_device *dev, pm_message_t state
 	/* -- end of hibernation path */
 
 
-#if defined(FG_BAT_INT)
+#if defined(FG_BAT_INT_OLD)
 #if defined(CONFIG_POWER_EXT)
 #elif defined(SOC_BY_HW_FG)
 	if (reset_fg_bat_int == KAL_TRUE) {
@@ -3263,7 +3372,7 @@ static int battery_meter_suspend(struct platform_device *dev, pm_message_t state
 	}
 #endif
 #else
-#endif				/* #if defined(FG_BAT_INT) */
+#endif	/* #if defined(FG_BAT_INT_OLD) */
 
 #if defined(CONFIG_POWER_EXT)
 
@@ -3327,6 +3436,9 @@ static int battery_meter_resume(struct platform_device *dev)
 
 #if defined(SOC_BY_HW_FG)
 #ifdef MTK_ENABLE_AGING_ALGORITHM
+	/* read HW ocv ready bit here, daemon resume flow will get it later */
+	battery_meter_ctrl(BATTERY_METER_CMD_GET_IS_HW_OCV_READY, &is_hwocv_update);
+
 	if (g_sleep_total_time.tv_sec < g_spm_timer) {
 		if (wake_up_smooth_time == 0) {
 			if (bat_is_charger_exist() == KAL_FALSE) {
@@ -4038,6 +4150,7 @@ void bmd_ctrl_cmd_from_user(void *nl_data, struct fgd_nl_msg_t *ret_msg)
 	case FG_DAEMON_CMD_SET_INIT_FLAG:
 		{
 			memcpy(&init_flag, &msg->fgd_data[0], sizeof(init_flag));
+
 			bm_notice("[fg_res] init_flag = %d\n", init_flag);
 		}
 		break;
@@ -4161,6 +4274,13 @@ void bmd_ctrl_cmd_from_user(void *nl_data, struct fgd_nl_msg_t *ret_msg)
 		}
 		break;
 
+	case FG_DAEMON_CMD_PRINT_LOG:
+		{
+			/* bm_err("FG_DAEMON_CMD_PRINT_LOG\n"); */
+			bm_err("%s", &msg->fgd_data[0]);
+		}
+		break;
+
 	default:
 		bm_debug("bad FG_DAEMON_CTRL_CMD_FROM_USER 0x%x\n", msg->fgd_cmd);
 		break;

+ 3 - 0
drivers/scsi/sg.c

@@ -1785,6 +1785,9 @@ sg_start_req(Sg_request *srp, unsigned char *cmd)
 			md->from_user = 0;
 	}
 
+	if (unlikely(iov_count > UIO_MAXIOV))
+		return -EINVAL;
+
 	if (iov_count) {
 		int len, size = sizeof(struct sg_iovec) * iov_count;
 		struct iovec *iov;

+ 1 - 1
drivers/watchdog/mediatek/wdk/wd_common_drv.c

@@ -618,7 +618,7 @@ ssize_t mtk_rgu_pause_wdt_store(struct kobject *kobj, const char *buffer, size_t
 {
 	char pause_wdt;
 	int pause_wdt_b;
-	int res = sscanf(buffer, "%s", &pause_wdt);
+	int res = sscanf(buffer, "%c", &pause_wdt);
 
 	pause_wdt_b = pause_wdt;
 

+ 14 - 3
fs/timerfd.c

@@ -40,6 +40,7 @@ struct timerfd_ctx {
 	short unsigned settime_flags;	/* to show in fdinfo */
 	struct rcu_head rcu;
 	struct list_head clist;
+	spinlock_t cancel_lock;
 	bool might_cancel;
 };
 
@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void)
 	rcu_read_unlock();
 }
 
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
 {
 	if (ctx->might_cancel) {
 		ctx->might_cancel = false;
@@ -122,6 +123,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
 	}
 }
 
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+{
+	spin_lock(&ctx->cancel_lock);
+	__timerfd_remove_cancel(ctx);
+	spin_unlock(&ctx->cancel_lock);
+}
+
 static bool timerfd_canceled(struct timerfd_ctx *ctx)
 {
 	if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -132,6 +140,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
 
 static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
 {
+	spin_lock(&ctx->cancel_lock);
 	if ((ctx->clockid == CLOCK_REALTIME ||
 	     ctx->clockid == CLOCK_REALTIME_ALARM) &&
 	    (flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
 			list_add_rcu(&ctx->clist, &cancel_list);
 			spin_unlock(&cancel_lock);
 		}
-	} else if (ctx->might_cancel) {
-		timerfd_remove_cancel(ctx);
+	} else {
+		__timerfd_remove_cancel(ctx);
 	}
+	spin_unlock(&ctx->cancel_lock);
 }
 
 static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -394,6 +404,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
 		return -ENOMEM;
 
 	init_waitqueue_head(&ctx->wqh);
+	spin_lock_init(&ctx->cancel_lock);
 	ctx->clockid = clockid;
 
 	if (isalarm(ctx))

+ 8 - 1
net/ipv4/ip_sockglue.c

@@ -1066,7 +1066,14 @@ void ipv4_pktinfo_prepare(const struct sock *sk, struct sk_buff *skb)
 		pktinfo->ipi_ifindex = 0;
 		pktinfo->ipi_spec_dst.s_addr = 0;
 	}
-	skb_dst_drop(skb);
+	/* We need to keep the dst for __ip_options_echo()
+	 * We could restrict the test to opt.ts_needtime || opt.srr,
+	 * but the following is good enough as IP options are not often used.
+	 */
+	if (unlikely(IPCB(skb)->opt.optlen))
+		skb_dst_force(skb);
+	else
+		skb_dst_drop(skb);
 }
 
 int ip_setsockopt(struct sock *sk, int level,

+ 18 - 8
net/packet/af_packet.c

@@ -3261,19 +3261,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
 		if (optlen != sizeof(val))
 			return -EINVAL;
-		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
 		switch (val) {
 		case TPACKET_V1:
 		case TPACKET_V2:
 		case TPACKET_V3:
-			po->tp_version = val;
-			return 0;
+			break;
 		default:
 			return -EINVAL;
 		}
+		lock_sock(sk);
+		if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+			ret = -EBUSY;
+		} else {
+			po->tp_version = val;
+			ret = 0;
+		}
+		release_sock(sk);
+		return ret;
 	}
 	case PACKET_RESERVE:
 	{
@@ -3285,6 +3291,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 			return -EBUSY;
 		if (copy_from_user(&val, optval, sizeof(val)))
 			return -EFAULT;
+		if (val > INT_MAX)
+			return -EINVAL;
 		po->tp_reserve = val;
 		return 0;
 	}
@@ -3736,6 +3744,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 	/* Added to avoid minimal code churn */
 	struct tpacket_req *req = &req_u->req;
 
+	lock_sock(sk);
 	/* Opening a Tx-ring is NOT supported in TPACKET_V3 */
 	if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
 		WARN(1, "Tx-ring is not supported.\n");
@@ -3777,8 +3786,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		if (unlikely(req->tp_block_size & (PAGE_SIZE - 1)))
 			goto out;
 		if (po->tp_version >= TPACKET_V3 &&
-		    (int)(req->tp_block_size -
-			  BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
+		    req->tp_block_size <=
+			 BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
 			goto out;
 		if (unlikely(req->tp_frame_size < po->tp_hdrlen +
 					po->tp_reserve))
@@ -3789,6 +3798,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		rb->frames_per_block = req->tp_block_size/req->tp_frame_size;
 		if (unlikely(rb->frames_per_block <= 0))
 			goto out;
+		if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+			goto out;
 		if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
 					req->tp_frame_nr))
 			goto out;
@@ -3817,7 +3828,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 			goto out;
 	}
 
-	lock_sock(sk);
 
 	/* Detach socket from network */
 	spin_lock(&po->bind_lock);
@@ -3866,11 +3876,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 		if (!tx_ring)
 			prb_shutdown_retire_blk_timer(po, tx_ring, rb_queue);
 	}
-	release_sock(sk);
 
 	if (pg_vec)
 		free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
+	release_sock(sk);
 	return err;
 }