summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/power/power_supply_sysfs.c7
-rw-r--r--drivers/power/reset/msm-poweroff.c11
-rw-r--r--drivers/power/supply/qcom/battery.c94
-rw-r--r--drivers/power/supply/qcom/fg-core.h9
-rw-r--r--drivers/power/supply/qcom/fg-memif.c60
-rw-r--r--drivers/power/supply/qcom/fg-reg.h27
-rw-r--r--drivers/power/supply/qcom/fg-util.c8
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c309
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c368
-rw-r--r--drivers/power/supply/qcom/smb-lib.c455
-rw-r--r--drivers/power/supply/qcom/smb-lib.h32
-rw-r--r--drivers/power/supply/qcom/smb-reg.h14
-rw-r--r--drivers/power/supply/qcom/smb1351-charger.c48
-rw-r--r--drivers/power/supply/qcom/step-chg-jeita.c68
-rw-r--r--include/linux/input/qpnp-power-on.h18
-rw-r--r--include/linux/power_supply.h4
16 files changed, 1531 insertions, 1 deletions
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 96853c18bc43..e50048db052b 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -60,6 +60,9 @@ static ssize_t power_supply_show_property(struct device *dev,
"Unknown", "Good", "Overheat", "Dead", "Over voltage",
"Unspecified failure", "Cold", "Watchdog timer expire",
"Safety timer expire",
+#ifdef CONFIG_MACH_LONGCHEER
+ "Low_Cool",
+#endif
"Warm", "Cool", "Hot"
};
static char *technology_text[] = {
@@ -305,6 +308,10 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(pd_voltage_max),
POWER_SUPPLY_ATTR(pd_voltage_min),
POWER_SUPPLY_ATTR(sdp_current_max),
+#ifdef CONFIG_MACH_LONGCHEER
+ POWER_SUPPLY_ATTR(fg_reset_clock),
+ POWER_SUPPLY_ATTR(rerun_apsd),
+#endif
POWER_SUPPLY_ATTR(fcc_stepper_enable),
POWER_SUPPLY_ATTR(ignore_false_negative_isense),
POWER_SUPPLY_ATTR(battery_info),
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index 47b22b7e9d1d..78ef4df9c9e2 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -358,8 +358,19 @@ static void msm_restart_prepare(const char *cmd)
} else if (!strncmp(cmd, "edl", 3)) {
enable_emergency_dload_mode();
} else {
+#ifdef CONFIG_MACH_LONGCHEER
+ qpnp_pon_set_restart_reason(PON_RESTART_REASON_NORMAL);
+#endif
__raw_writel(0x77665501, restart_reason);
}
+#ifdef CONFIG_MACH_LONGCHEER
+ } else if (in_panic) {
+ qpnp_pon_set_restart_reason(PON_RESTART_REASON_PANIC);
+ qpnp_pon_system_pwr_off(PON_POWER_OFF_WARM_RESET);
+ } else {
+ qpnp_pon_set_restart_reason(PON_RESTART_REASON_NORMAL);
+ __raw_writel(0x77665501, restart_reason);
+#endif
}
flush_cache_all();
diff --git a/drivers/power/supply/qcom/battery.c b/drivers/power/supply/qcom/battery.c
index afae88ea044a..fc6a589d9e68 100644
--- a/drivers/power/supply/qcom/battery.c
+++ b/drivers/power/supply/qcom/battery.c
@@ -41,6 +41,9 @@
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
#define USBIN_I_VOTER "USBIN_I_VOTER"
#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
+#ifdef CONFIG_MACH_LONGCHEER
+#define PL_TEMP_VOTER "PL_TEMP_VOTER"
+#endif
struct pl_data {
int pl_mode;
@@ -87,7 +90,11 @@ enum print_reason {
PR_PARALLEL = BIT(0),
};
+#ifdef CONFIG_MACH_LONGCHEER
+static int debug_mask = 0xff;
+#else
static int debug_mask;
+#endif
module_param_named(debug_mask, debug_mask, int, S_IRUSR | S_IWUSR);
#define pl_dbg(chip, reason, fmt, ...) \
@@ -105,6 +112,10 @@ enum {
RESTRICT_CHG_CURRENT,
};
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+#define ONLY_PM660_CURRENT_UA 2000000
+#endif
+
/*******
* ICL *
********/
@@ -194,6 +205,15 @@ static void split_settled(struct pl_data *chip)
}
pval.intval = total_current_ua - slave_ua;
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+ if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) {
+ pr_err("pl_disable_votable effective main_psy current_ua =%d \n", pval.intval);
+ if (get_effective_result_locked(chip->pl_disable_votable) && (pval.intval > ONLY_PM660_CURRENT_UA)) {
+ pr_err("pl_disable_votable effective main_psy force current_ua =%d to %d \n", pval.intval, ONLY_PM660_CURRENT_UA);
+ pval.intval = ONLY_PM660_CURRENT_UA;
+ }
+ }
+#endif
/* Set ICL on main charger */
rc = power_supply_set_property(chip->main_psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
@@ -332,7 +352,11 @@ static struct class_attribute pl_attributes[] = {
* TAPER *
************/
#define MINIMUM_PARALLEL_FCC_UA 500000
+#ifdef CONFIG_MACH_LONGCHEER
+#define PL_TAPER_WORK_DELAY_MS 100
+#else
#define PL_TAPER_WORK_DELAY_MS 500
+#endif
#define TAPER_RESIDUAL_PCT 75
static void pl_taper_work(struct work_struct *work)
{
@@ -528,6 +552,15 @@ static int pl_fcc_vote_callback(struct votable *votable, void *data,
return 0;
}
pval.intval = total_fcc_ua;
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+ if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) {
+ pr_err("pl_disable_votable effective total_fcc_ua =%d \n", total_fcc_ua);
+ if (pval.intval > ONLY_PM660_CURRENT_UA) {
+ pval.intval = ONLY_PM660_CURRENT_UA;
+ pr_err("pl_disable_votable effective total_fcc_ua =%d froce to %d \n", total_fcc_ua, pval.intval);
+ }
+ }
+#endif
rc = power_supply_set_property(chip->main_psy,
POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
&pval);
@@ -797,7 +830,11 @@ stepper_exit:
}
}
+#ifdef CONFIG_MACH_LONGCHEER
+#define PARALLEL_FLOAT_VOLTAGE_DELTA_UV 100000
+#else
#define PARALLEL_FLOAT_VOLTAGE_DELTA_UV 50000
+#endif
static int pl_fv_vote_callback(struct votable *votable, void *data,
int fv_uv, const char *client)
{
@@ -865,7 +902,11 @@ static int usb_icl_vote_callback(struct votable *votable, void *data,
* unvote USBIN_I_VOTER) the status_changed_work enables
* USBIN_I_VOTER based on settled current.
*/
+#ifdef CONFIG_MACH_LONGCHEER
+ if (icl_ua <= 1300000)
+#else
if (icl_ua <= 1400000)
+#endif
vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
else
schedule_delayed_work(&chip->status_change_work,
@@ -1169,6 +1210,10 @@ static void handle_settled_icl_change(struct pl_data *chip)
int main_settled_ua;
int main_limited;
int total_current_ua;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ int battery_temp;
+ union power_supply_propval lct_pval = {0, };
+#endif
total_current_ua = get_effective_result_locked(chip->usb_icl_votable);
@@ -1194,13 +1239,62 @@ static void handle_settled_icl_change(struct pl_data *chip)
}
main_limited = pval.intval;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if (chip->pl_mode == POWER_SUPPLY_PL_USBIN_USBIN) {
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_TEMP,
+ &lct_pval);
+ if (rc < 0) {
+ pr_err("Couldn't battery health value rc=%d\n", rc);
+ return;
+ }
+ battery_temp = lct_pval.intval;
+ pr_err("main_limited=%d, main_settled_ua=%d, chip->pl_settled_ua=%d ,total_current_ua=%d , battery_temp=%d\n", main_limited, main_settled_ua, chip->pl_settled_ua, total_current_ua, battery_temp);
+ if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1300000)
+ || (main_settled_ua == 0)
+ || ((total_current_ua >= 0) &&
+ (total_current_ua <= 1300000))){
+ pr_err("total_current_ua <= 1300000 disable parallel charger smb1351 \n");
+ vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+ vote(chip->pl_disable_votable, PL_TEMP_VOTER, true, 0);
+ } else {
+ if ((battery_temp > 20) && (battery_temp < 440)) {
+ vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);
+ vote(chip->pl_disable_votable, PL_TEMP_VOTER, false, 0);
+ } else {
+ vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+ vote(chip->pl_disable_votable, PL_TEMP_VOTER, true, 0);
+ }
+ }
+ } else {
+ pr_err("main_limited=%d, main_settled_ua=%d, chip->pl_settled_ua=%d ,total_current_ua=%d\n", main_limited, main_settled_ua, chip->pl_settled_ua, total_current_ua);
+ if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1300000)
+ || (main_settled_ua == 0)
+ || ((total_current_ua >= 0) &&
+ (total_current_ua <= 1300000))){
+ pr_err("total_current_ua <= 1300000 disable parallel charger smb1351 \n");
+ vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+ } else
+ vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);
+ }
+#else
+ pr_err("main_limited=%d, main_settled_ua=%d, chip->pl_settled_ua=%d ,total_current_ua=%d\n", main_limited, main_settled_ua, chip->pl_settled_ua, total_current_ua);
+#ifdef CONFIG_MACH_LONGCHEER
+ if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1300000)
+#else
if ((main_limited && (main_settled_ua + chip->pl_settled_ua) < 1400000)
+#endif
|| (main_settled_ua == 0)
|| ((total_current_ua >= 0) &&
+#ifdef CONFIG_MACH_LONGCHEER
+ (total_current_ua <= 1300000)))
+#else
(total_current_ua <= 1400000)))
+#endif
vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
else
vote(chip->pl_enable_votable_indirect, USBIN_I_VOTER, true, 0);
+#endif
if (get_effective_result(chip->pl_disable_votable))
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 076cd49e6dd5..0ea3dd295af8 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -438,6 +438,9 @@ struct fg_chip {
int last_recharge_volt_mv;
int delta_temp_irq_count;
int esr_timer_charging_default[NUM_ESR_TIMERS];
+#ifdef CONFIG_MACH_LONGCHEER
+ int battery_full_design;
+#endif
enum slope_limit_status slope_limit_sts;
enum esr_filter_status esr_flt_sts;
bool profile_available;
@@ -445,6 +448,9 @@ struct fg_chip {
bool battery_missing;
bool fg_restarting;
bool charge_full;
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ bool report_full;
+#endif
bool recharge_soc_adjusted;
bool ki_coeff_dischg_en;
bool esr_fcc_ctrl_en;
@@ -522,4 +528,7 @@ extern void fg_circ_buf_clr(struct fg_circ_buf *);
extern int fg_circ_buf_avg(struct fg_circ_buf *, int *);
extern int fg_circ_buf_median(struct fg_circ_buf *, int *);
extern int fg_lerp(const struct fg_pt *, size_t, s32, s32 *);
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+extern int fg_dma_mem_req(struct fg_chip *, bool);
+#endif
#endif
diff --git a/drivers/power/supply/qcom/fg-memif.c b/drivers/power/supply/qcom/fg-memif.c
index 8a949bfe61d0..0d668d6260da 100644
--- a/drivers/power/supply/qcom/fg-memif.c
+++ b/drivers/power/supply/qcom/fg-memif.c
@@ -746,6 +746,66 @@ out:
return rc;
}
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+int fg_dma_mem_req(struct fg_chip *chip, bool request)
+{
+ int ret, rc = 0, retry_count = RETRY_COUNT;
+ u8 val;
+
+ if (request) {
+ /* configure for DMA access */
+ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
+ MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT,
+ MEM_ACCESS_REQ_BIT);
+ if (rc < 0) {
+ pr_err("failed to set mem_access bit rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip),
+ MEM_IF_ARB_REQ_BIT, MEM_IF_ARB_REQ_BIT);
+ if (rc < 0) {
+ pr_err("failed to set mem_arb bit rc=%d\n", rc);
+ goto release_mem;
+ }
+
+ while (retry_count--) {
+ rc = fg_read(chip, MEM_IF_INT_RT_STS(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("failed to set ima_rt_sts rc=%d\n", rc);
+ goto release_mem;
+ }
+ if (val & MEM_GNT_BIT)
+ break;
+ msleep(20);
+ }
+ if (!retry_count && !(val & MEM_GNT_BIT)) {
+ pr_err("failed to get memory access\n");
+ rc = -ETIMEDOUT;
+ goto release_mem;
+ }
+
+ return 0;
+ }
+
+release_mem:
+ /* Release access */
+ rc = fg_masked_write(chip, MEM_IF_MEM_INTF_CFG(chip),
+ MEM_ACCESS_REQ_BIT | IACS_SLCT_BIT, 0);
+ if (rc < 0)
+ pr_err("failed to reset mem_access bit rc = %d\n", rc);
+
+ ret = fg_masked_write(chip, MEM_IF_MEM_ARB_CFG(chip),
+ MEM_IF_ARB_REQ_BIT, 0);
+ if (ret < 0) {
+ pr_err("failed to release mem_arb bit rc=%d\n", ret);
+ return ret;
+ }
+
+ return rc;
+}
+#endif
+
int fg_ima_init(struct fg_chip *chip)
{
int rc;
diff --git a/drivers/power/supply/qcom/fg-reg.h b/drivers/power/supply/qcom/fg-reg.h
index cd0b2fb4391f..2ee383b733e0 100644
--- a/drivers/power/supply/qcom/fg-reg.h
+++ b/drivers/power/supply/qcom/fg-reg.h
@@ -29,6 +29,9 @@
#define BATT_SOC_STS_CLR(chip) (chip->batt_soc_base + 0x4A)
#define BATT_SOC_LOW_PWR_CFG(chip) (chip->batt_soc_base + 0x52)
#define BATT_SOC_LOW_PWR_STS(chip) (chip->batt_soc_base + 0x56)
+#ifdef CONFIG_MACH_LONGCHEER
+#define BATT_SOC_RST_CTRL0(chip) (chip->batt_soc_base + 0xBA)
+#endif
/* BATT_SOC_INT_RT_STS */
#define MSOC_EMPTY_BIT BIT(5)
@@ -39,6 +42,11 @@
/* BATT_SOC_RESTART */
#define RESTART_GO_BIT BIT(0)
+#ifdef CONFIG_MACH_LONGCHEER
+/* BCL_RESET */
+#define BCL_RESET_BIT BIT(2)
+#endif
+
/* FG_BATT_INFO register definitions */
#define BATT_INFO_BATT_TEMP_STS(chip) (chip->batt_info_base + 0x06)
#define BATT_INFO_SYS_BATT(chip) (chip->batt_info_base + 0x07)
@@ -95,6 +103,10 @@
#define BATT_INFO_IADC_MSB(chip) (chip->batt_info_base + 0xAF)
#define BATT_INFO_TM_MISC(chip) (chip->batt_info_base + 0xE5)
#define BATT_INFO_TM_MISC1(chip) (chip->batt_info_base + 0xE6)
+#ifdef CONFIG_MACH_LONGCHEER
+#define BATT_INFO_PEEK_MUX1(chip) (chip->batt_info_base + 0xEB)
+#define BATT_INFO_RDBACK(chip) (chip->batt_info_base + 0xEF)
+#endif
/* BATT_INFO_BATT_TEMP_STS */
#define JEITA_TOO_HOT_STS_BIT BIT(7)
@@ -264,8 +276,16 @@
#define ESR_REQ_CTL_BIT BIT(1)
#define ESR_REQ_CTL_EN_BIT BIT(0)
+#ifdef CONFIG_MACH_LONGCHEER
+/* BATT_INFO_PEEK_MUX1 */
+#define PEEK_MUX1_BIT BIT(0)
+#endif
+
/* FG_MEM_IF register and bit definitions */
#define MEM_IF_INT_RT_STS(chip) ((chip->mem_if_base) + 0x10)
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+#define MEM_IF_MEM_ARB_CFG(chip) ((chip->mem_if_base) + 0x40)
+#endif
#define MEM_IF_MEM_INTF_CFG(chip) ((chip->mem_if_base) + 0x50)
#define MEM_IF_IMA_CTL(chip) ((chip->mem_if_base) + 0x51)
#define MEM_IF_IMA_CFG(chip) ((chip->mem_if_base) + 0x52)
@@ -286,6 +306,9 @@
/* MEM_IF_INT_RT_STS */
#define MEM_XCP_BIT BIT(1)
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+#define MEM_GNT_BIT BIT(2)
+#endif
/* MEM_IF_MEM_INTF_CFG */
#define MEM_ACCESS_REQ_BIT BIT(7)
@@ -326,4 +349,8 @@
/* MEM_IF_DMA_CTL */
#define DMA_CLEAR_LOG_BIT BIT(0)
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+/* MEM_IF_REQ */
+#define MEM_IF_ARB_REQ_BIT BIT(0)
+#endif
#endif
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index 23dd9131d402..3d1ca7990883 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.c
@@ -420,7 +420,11 @@ int fg_write(struct fg_chip *chip, int addr, u8 *val, int len)
return -ENXIO;
mutex_lock(&chip->bus_lock);
+#if defined(CONFIG_MACH_XIAOMI_TULIP) || defined(CONFIG_MACH_XIAOMI_WAYNE)
+ sec_access = (addr & 0x00FF) > 0xBA;
+#else
sec_access = (addr & 0x00FF) > 0xD0;
+#endif
if (sec_access) {
rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
if (rc < 0) {
@@ -460,7 +464,11 @@ int fg_masked_write(struct fg_chip *chip, int addr, u8 mask, u8 val)
return -ENXIO;
mutex_lock(&chip->bus_lock);
+#if defined(CONFIG_MACH_XIAOMI_TULIP) || defined(CONFIG_MACH_XIAOMI_WAYNE)
+ sec_access = (addr & 0x00FF) > 0xBA;
+#else
sec_access = (addr & 0x00FF) > 0xD0;
+#endif
if (sec_access) {
rc = regmap_write(chip->regmap, (addr & 0xFF00) | 0xD0, 0xA5);
if (rc < 0) {
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 243c865e6877..750a08d14f53 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -20,6 +20,9 @@
#include <linux/platform_device.h>
#include <linux/iio/consumer.h>
#include <linux/qpnp/qpnp-revid.h>
+#ifdef CONFIG_MACH_LONGCHEER
+#include <linux/thermal.h>
+#endif
#include "fg-core.h"
#include "fg-reg.h"
@@ -407,6 +410,14 @@ module_param_named(
static int fg_restart;
static bool fg_sram_dump;
+#ifdef CONFIG_MACH_LONGCHEER
+int hwc_check_india;
+int hwc_check_global;
+extern bool is_poweroff_charge;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+extern int rradc_die;
+#endif
+#endif
/* All getters HERE */
@@ -638,6 +649,9 @@ static int fg_get_battery_temp(struct fg_chip *chip, int *val)
{
int rc = 0, temp;
u8 buf[2];
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ struct thermal_zone_device *quiet_them;
+#endif
rc = fg_read(chip, BATT_INFO_BATT_TEMP_LSB(chip), buf, 2);
if (rc < 0) {
@@ -652,6 +666,66 @@ static int fg_get_battery_temp(struct fg_chip *chip, int *val)
/* Value is in Kelvin; Convert it to deciDegC */
temp = (temp - 273) * 10;
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if (temp < -40) {
+ switch (temp) {
+ case -50:
+ temp = -70;
+ break;
+ case -60:
+ temp = -80;
+ break;
+ case -70:
+ temp = -90;
+ break;
+ case -80:
+ temp = -100;
+ break;
+#else
+ if (temp < -80) {
+ switch (temp) {
+#endif
+ case -90:
+ temp = -110;
+ break;
+ case -100:
+ temp = -120;
+ break;
+ case -110:
+ temp = -130;
+ break;
+ case -120:
+ temp = -150;
+ break;
+ case -130:
+ temp = -170;
+ break;
+ case -140:
+ temp = -190;
+ break;
+ case -150:
+ temp = -200;
+ break;
+ case -160:
+ temp = -210;
+ break;
+ default:
+ temp -= 50;
+ break;
+ };
+ }
+
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if (rradc_die) {
+ quiet_them = thermal_zone_get_zone_by_name("quiet_therm");
+ if (quiet_them)
+ rc = thermal_zone_get_temp(quiet_them, &temp);
+ temp = (temp - 3) * 10;
+ pr_err("LCT USE QUIET_THERM AS BATTERY TEMP \n");
+ }
+#endif
+#endif
*val = temp;
return 0;
}
@@ -760,6 +834,9 @@ static int fg_get_msoc_raw(struct fg_chip *chip, int *val)
#define FULL_CAPACITY 100
#define FULL_SOC_RAW 255
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+#define FULL_SOC_REPORT_THR 250
+#endif
static int fg_get_msoc(struct fg_chip *chip, int *msoc)
{
int rc;
@@ -776,6 +853,16 @@ static int fg_get_msoc(struct fg_chip *chip, int *msoc)
*/
if (*msoc == FULL_SOC_RAW)
*msoc = 100;
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ else if ((*msoc >= FULL_SOC_REPORT_THR - 2)
+ && (*msoc < FULL_SOC_RAW) && chip->report_full) {
+ *msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW) + 1;
+ if (*msoc >= FULL_CAPACITY)
+ *msoc = FULL_CAPACITY;
+ } else if (*msoc >= FULL_SOC_REPORT_THR - 4
+ && *msoc <= FULL_SOC_REPORT_THR - 3 && chip->report_full)
+ *msoc = DIV_ROUND_CLOSEST(*msoc * FULL_CAPACITY, FULL_SOC_RAW);
+#endif
else if (*msoc == 0)
*msoc = 0;
else
@@ -978,6 +1065,22 @@ out:
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+static int __init hwc_setup(char *s)
+{
+ if (strcmp(s, "India") == 0)
+ hwc_check_india = 1;
+ else
+ hwc_check_india = 0;
+ if (strcmp(s, "Global") == 0)
+ hwc_check_global = 1;
+ else
+ hwc_check_global = 0;
+ return 1;
+}
+__setup("androidboot.hwc=", hwc_setup);
+#endif
+
static int fg_get_batt_profile(struct fg_chip *chip)
{
struct device_node *node = chip->dev->of_node;
@@ -1022,6 +1125,20 @@ static int fg_get_batt_profile(struct fg_chip *chip)
chip->bp.fastchg_curr_ma = -EINVAL;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ if (hwc_check_global)
+ chip->bp.fastchg_curr_ma = 2300;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ else
+ if (is_poweroff_charge) {
+ if (hwc_check_india)
+ chip->bp.fastchg_curr_ma = 2200;
+ else
+ chip->bp.fastchg_curr_ma = 2300;
+ }
+#endif
+#endif
+
rc = of_property_read_u32(profile_node, "qcom,fg-cc-cv-threshold-mv",
&chip->bp.vbatt_full_mv);
if (rc < 0) {
@@ -1035,6 +1152,14 @@ static int fg_get_batt_profile(struct fg_chip *chip)
return -ENODATA;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ rc = of_property_read_u32(profile_node, "qcom,battery-full-design", &chip->battery_full_design);
+ if (rc < 0) {
+ pr_err("No profile data available\n");
+ return -ENODATA;
+ }
+#endif
+
if (len != PROFILE_LEN) {
pr_err("battery profile incorrect size: %d\n", len);
return -EINVAL;
@@ -2148,9 +2273,28 @@ static int fg_adjust_recharge_voltage(struct fg_chip *chip)
recharge_volt_mv = chip->dt.recharge_volt_thr_mv;
/* Lower the recharge voltage in soft JEITA */
+#ifdef CONFIG_MACH_LONGCHEER
+#if defined(CONFIG_MACH_XIAOMI_WHYRED)
+ if (chip->health == POWER_SUPPLY_HEALTH_WARM)
+ recharge_volt_mv = 4050;
+ if (chip->health == POWER_SUPPLY_HEALTH_COOL)
+ recharge_volt_mv = 4282;
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ if (chip->health == POWER_SUPPLY_HEALTH_WARM)
+ recharge_volt_mv = 4050;
+ if (chip->health == POWER_SUPPLY_HEALTH_COOL)
+ recharge_volt_mv = 4250;
+#else
+ if (chip->health == POWER_SUPPLY_HEALTH_WARM)
+ recharge_volt_mv = 4050;
+ if (chip->health == POWER_SUPPLY_HEALTH_COOL)
+ recharge_volt_mv = 4280;
+#endif
+#else
if (chip->health == POWER_SUPPLY_HEALTH_WARM ||
chip->health == POWER_SUPPLY_HEALTH_COOL)
recharge_volt_mv -= 200;
+#endif
rc = fg_set_recharge_voltage(chip, recharge_volt_mv);
if (rc < 0) {
@@ -2713,6 +2857,9 @@ static void status_change_work(struct work_struct *work)
struct fg_chip, status_change_work);
union power_supply_propval prop = {0, };
int rc, batt_temp;
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ int msoc;
+#endif
if (!batt_psy_initialized(chip)) {
fg_dbg(chip, FG_STATUS, "Charger not available?!\n");
@@ -2746,6 +2893,18 @@ static void status_change_work(struct work_struct *work)
fg_cycle_counter_update(chip);
fg_cap_learning_update(chip);
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ if (chip->charge_done && !chip->report_full) {
+ chip->report_full = true;
+ } else if (!chip->charge_done && chip->report_full) {
+ rc = fg_get_msoc_raw(chip, &msoc);
+ if (rc < 0)
+ pr_err("Error in getting msoc, rc=%d\n", rc);
+ if (msoc < FULL_SOC_REPORT_THR - 4)
+ chip->report_full = false;
+ }
+#endif
+
rc = fg_charge_full_update(chip);
if (rc < 0)
pr_err("Error in charge_full_update, rc=%d\n", rc);
@@ -3850,6 +4009,11 @@ static int fg_psy_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CC_STEP_SEL:
pval->intval = chip->ttf.cc_step.sel;
break;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ case POWER_SUPPLY_PROP_FG_RESET_CLOCK:
+ pval->intval = 0;
+ break;
+#endif
default:
pr_err("unsupported property %d\n", psp);
rc = -EINVAL;
@@ -3862,6 +4026,102 @@ static int fg_psy_get_property(struct power_supply *psy,
return 0;
}
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+#define BCL_RESET_RETRY_COUNT 4
+static int fg_bcl_reset(struct fg_chip *chip)
+{
+ int i, ret, rc = 0;
+ u8 val, peek_mux;
+ bool success = false;
+ pr_err("FG_BCL_RESET START\n");
+ /* Read initial value of peek mux1 */
+ rc = fg_read(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1);
+ if (rc < 0) {
+ pr_err("Error in writing peek mux1, rc=%d\n", rc);
+ return rc;
+ }
+ pr_err("FG_BCL_RESET PEEK_MUX = %d\n",peek_mux);
+ val = 0x83;
+ rc = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("Error in writing peek mux1, rc=%d\n", rc);
+ return rc;
+ }
+
+ mutex_lock(&chip->sram_rw_lock);
+ for (i = 0; i < BCL_RESET_RETRY_COUNT; i++) {
+ pr_err("FG_BCL_RESET RETRY\n");
+ rc = fg_dma_mem_req(chip, true);
+ if (rc < 0) {
+ pr_err("Error in locking memory, rc=%d\n", rc);
+ goto unlock;
+ }
+
+ rc = fg_read(chip, BATT_INFO_RDBACK(chip), &val, 1);
+ if (rc < 0) {
+ pr_err("Error in reading rdback, rc=%d\n", rc);
+ goto release_mem;
+ }
+ pr_err("FG_BCL_RESET VAL = %d\n",val);
+ if (val & PEEK_MUX1_BIT) {
+ pr_err("FG_BCL_RESET DEBUG\n");
+ rc = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip),
+ BCL_RESET_BIT, BCL_RESET_BIT);
+ if (rc < 0) {
+ pr_err("Error in writing RST_CTRL0, rc=%d\n",
+ rc);
+ goto release_mem;
+ }
+
+ rc = fg_dma_mem_req(chip, false);
+ if (rc < 0)
+ pr_err("Error in unlocking memory, rc=%d\n", rc);
+
+ /* Delay of 2ms */
+ usleep_range(2000, 3000);
+ ret = fg_masked_write(chip, BATT_SOC_RST_CTRL0(chip),
+ BCL_RESET_BIT, 0);
+ if (ret < 0)
+ pr_err("Error in writing RST_CTRL0, rc=%d\n",
+ rc);
+ if (!rc && !ret)
+ success = true;
+
+ goto unlock;
+ } else {
+ rc = fg_dma_mem_req(chip, false);
+ if (rc < 0) {
+ pr_err("Error in unlocking memory, rc=%d\n", rc);
+ return rc;
+ }
+ success = false;
+ pr_err_ratelimited("PEEK_MUX1 not set retrying...\n");
+ msleep(1000);
+ }
+ }
+
+release_mem:
+ rc = fg_dma_mem_req(chip, false);
+ if (rc < 0)
+ pr_err("Error in unlocking memory, rc=%d\n", rc);
+
+unlock:
+ ret = fg_write(chip, BATT_INFO_PEEK_MUX1(chip), &peek_mux, 1);
+ if (ret < 0) {
+ pr_err("Error in writing peek mux1, rc=%d\n", rc);
+ mutex_unlock(&chip->sram_rw_lock);
+ return ret;
+ }
+
+ mutex_unlock(&chip->sram_rw_lock);
+
+ if (!success)
+ return -EAGAIN;
+ else
+ return rc;
+}
+#endif
+
static int fg_psy_set_property(struct power_supply *psy,
enum power_supply_property psp,
const union power_supply_propval *pval)
@@ -3908,6 +4168,15 @@ static int fg_psy_set_property(struct power_supply *psy,
return -EINVAL;
}
break;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ case POWER_SUPPLY_PROP_FG_RESET_CLOCK:
+ rc = fg_bcl_reset(chip);
+ if (rc < 0) {
+ pr_err("Error in resetting BCL clock, rc=%d\n", rc);
+ return rc;
+ }
+ break;
+#endif
case POWER_SUPPLY_PROP_CHARGE_FULL:
if (chip->cl.active) {
pr_warn("Capacity learning active!\n");
@@ -3965,6 +4234,9 @@ static int fg_property_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
case POWER_SUPPLY_PROP_CC_STEP:
case POWER_SUPPLY_PROP_CC_STEP_SEL:
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ case POWER_SUPPLY_PROP_FG_RESET_CLOCK:
+#endif
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_COLD_TEMP:
case POWER_SUPPLY_PROP_COOL_TEMP:
@@ -4047,6 +4319,9 @@ static enum power_supply_property fg_psy_props[] = {
POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
POWER_SUPPLY_PROP_CC_STEP,
POWER_SUPPLY_PROP_CC_STEP_SEL,
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ POWER_SUPPLY_PROP_FG_RESET_CLOCK,
+#endif
};
static const struct power_supply_desc fg_psy_desc = {
@@ -4148,6 +4423,9 @@ static int fg_hw_init(struct fg_chip *chip)
if (chip->dt.delta_soc_thr > 0 && chip->dt.delta_soc_thr < 100) {
fg_encode(chip->sp, FG_SRAM_DELTA_MSOC_THR,
chip->dt.delta_soc_thr, buf);
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ buf[0] = 0x8;
+#endif
rc = fg_sram_write(chip,
chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_word,
chip->sp[FG_SRAM_DELTA_MSOC_THR].addr_byte,
@@ -4335,6 +4613,14 @@ static int fg_hw_init(struct fg_chip *chip)
}
}
+#ifdef CONFIG_MACH_LONGCHEER
+ buf[0] = 0x33;
+ buf[1] = 0x3;
+ rc = fg_sram_write(chip, 4, 0, buf, 2, FG_IMA_DEFAULT);
+ if (rc < 0)
+ pr_err("Error in configuring Sram, rc = %d\n", rc);
+#endif
+
return 0;
}
@@ -4538,6 +4824,11 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
{
struct fg_chip *chip = data;
int rc;
+#ifdef CONFIG_MACH_LONGCHEER
+ struct thermal_zone_device *quiet_them;
+ int msoc, volt_uv, batt_temp, ibatt_now,temp_qt ;
+ bool input_present;
+#endif
fg_dbg(chip, FG_IRQ, "irq %d triggered\n", irq);
fg_cycle_counter_update(chip);
@@ -4568,6 +4859,20 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data)
if (batt_psy_initialized(chip))
power_supply_changed(chip->batt_psy);
+#ifdef CONFIG_MACH_LONGCHEER
+ input_present = is_input_present(chip);
+ quiet_them = thermal_zone_get_zone_by_name("quiet_therm");
+ rc = fg_get_battery_voltage(chip, &volt_uv);
+ if (!rc)
+ rc = fg_get_prop_capacity(chip, &msoc);
+ if (!rc)
+ rc = fg_get_battery_temp(chip, &batt_temp);
+ if (quiet_them)
+ rc = thermal_zone_get_temp(quiet_them, &temp_qt);
+ if (!rc)
+ rc = fg_get_battery_current(chip, &ibatt_now);
+#endif
+
return IRQ_HANDLED;
}
@@ -4990,7 +5295,11 @@ static int fg_parse_dt(struct fg_chip *chip)
if (rc < 0)
chip->dt.sys_term_curr_ma = DEFAULT_SYS_TERM_CURR_MA;
else
+#ifdef CONFIG_MACH_LONGCHEER
+ chip->dt.sys_term_curr_ma = -temp;
+#else
chip->dt.sys_term_curr_ma = temp;
+#endif
rc = of_property_read_u32(node, "qcom,fg-chg-term-base-current", &temp);
if (rc < 0)
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 5fae7b99d88f..252e0cf54252 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -28,6 +28,39 @@
#include "smb-lib.h"
#include "storm-watch.h"
#include <linux/pmic-voter.h>
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+#include <linux/notifier.h>
+#include <linux/fb.h>
+
+union power_supply_propval lct_therm_lvl_reserved;
+union power_supply_propval lct_therm_level;
+#if defined(CONFIG_MACH_XIAOMI_WAYNE) || defined(CONFIG_MACH_XIAOMI_WHYRED)
+union power_supply_propval lct_therm_call_level = {4,};
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+union power_supply_propval lct_therm_call_level = {5,};
+#else
+union power_supply_propval lct_therm_call_level = {3,};
+#endif
+#if defined(CONFIG_MACH_XIAOMI_TULIP) || defined(CONFIG_MACH_XIAOMI_WHYRED)
+union power_supply_propval lct_therm_globe_level = {1,};
+union power_supply_propval lct_therm_india_level = {2,};
+#else
+union power_supply_propval lct_therm_globe_level = {2,};
+union power_supply_propval lct_therm_india_level = {1,};
+#endif
+
+bool lct_backlight_off;
+int LctIsInCall = 0;
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+int LctIsInVideo = 0;
+#endif
+int LctThermal = 0;
+extern int hwc_check_india;
+extern int hwc_check_global;
+extern bool is_poweroff_charge;
+#endif
+#endif
#define SMB2_DEFAULT_WPWR_UW 8000000
@@ -179,7 +212,11 @@ struct smb2 {
bool bad_part;
};
+#ifdef CONFIG_MACH_LONGCHEER
+static int __debug_mask = 0xFF;
+#else
static int __debug_mask;
+#endif
module_param_named(
debug_mask, __debug_mask, int, S_IRUSR | S_IWUSR
);
@@ -230,6 +267,19 @@ static int smb2_parse_dt(struct smb2 *chip)
"qcom,fcc-max-ua", &chg->batt_profile_fcc_ua);
if (rc < 0)
chg->batt_profile_fcc_ua = -EINVAL;
+#ifdef CONFIG_MACH_LONGCHEER
+ if (hwc_check_global) {
+ chg->batt_profile_fcc_ua = 2300000;
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if (is_poweroff_charge) {
+ if (hwc_check_india)
+ chg->batt_profile_fcc_ua = 2200000;
+ else
+ chg->batt_profile_fcc_ua = 2300000;
+ }
+#endif
+ }
+#endif
rc = of_property_read_u32(node,
"qcom,fv-max-uv", &chg->batt_profile_fv_uv);
@@ -274,6 +324,9 @@ static int smb2_parse_dt(struct smb2 *chip)
if (rc < 0)
chip->dt.wipower_max_uw = -EINVAL;
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ if (hwc_check_india) {
+#endif
if (of_find_property(node, "qcom,thermal-mitigation", &byte_len)) {
chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
GFP_KERNEL);
@@ -292,6 +345,28 @@ static int smb2_parse_dt(struct smb2 *chip)
return rc;
}
}
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ } else {
+ if (of_find_property(node, "qcom,thermal-mitigation-china", &byte_len)) {
+ chg->thermal_mitigation = devm_kzalloc(chg->dev, byte_len,
+ GFP_KERNEL);
+
+ if (chg->thermal_mitigation == NULL)
+ return -ENOMEM;
+
+ chg->thermal_levels = byte_len / sizeof(u32);
+ rc = of_property_read_u32_array(node,
+ "qcom,thermal-mitigation-china",
+ chg->thermal_mitigation,
+ chg->thermal_levels);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't read threm limits rc = %d\n", rc);
+ return rc;
+ }
+ }
+ }
+#endif
of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option);
if (chip->dt.float_option < 0 || chip->dt.float_option > 4) {
@@ -359,6 +434,9 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
+#ifdef CONFIG_MACH_LONGCHEER
+ POWER_SUPPLY_PROP_RERUN_APSD,
+#endif
};
static int smb2_usb_get_prop(struct power_supply *psy,
@@ -387,6 +465,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
val->intval = 0;
else
val->intval = 1;
+#ifdef CONFIG_MACH_LONGCHEER
+ if (is_poweroff_charge != false)
+#endif
if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
val->intval = 0;
break;
@@ -535,6 +616,11 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
rc = smblib_set_prop_sdp_current_max(chg, val);
break;
+#ifdef CONFIG_MACH_LONGCHEER
+ case POWER_SUPPLY_PROP_RERUN_APSD:
+ rc = smblib_set_prop_rerun_apsd(chg, val);
+ break;
+#endif
default:
pr_err("set prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -945,6 +1031,10 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_DP_DM,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE,
+#ifdef CONFIG_MACH_LONGCHEER
+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+ POWER_SUPPLY_PROP_CHARGING_ENABLED,
+#endif
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_CYCLE_COUNT,
};
@@ -958,6 +1048,11 @@ static int smb2_batt_get_prop(struct power_supply *psy,
union power_supply_propval pval = {0, };
switch (psp) {
+#ifdef CONFIG_MACH_LONGCHEER
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ val->intval = chg->charging_enabled;
+ break;
+#endif
case POWER_SUPPLY_PROP_STATUS:
rc = smblib_get_prop_batt_status(chg, val);
break;
@@ -1021,7 +1116,11 @@ static int smb2_batt_get_prop(struct power_supply *psy,
BATT_PROFILE_VOTER);
break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
+#ifdef CONFIG_MACH_LONGCHEER
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LIPO;
+#else
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+#endif
break;
case POWER_SUPPLY_PROP_CHARGE_DONE:
rc = smblib_get_prop_batt_charge_done(chg, val);
@@ -1040,6 +1139,11 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_DP_DM:
val->intval = chg->pulse_cnt;
break;
+#ifdef CONFIG_MACH_LONGCHEER
+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+ rc = smblib_get_prop_battery_full_design(chg, val);
+ break;
+#endif
case POWER_SUPPLY_PROP_RERUN_AICL:
val->intval = 0;
break;
@@ -1079,6 +1183,11 @@ static int smb2_batt_set_prop(struct power_supply *psy,
struct smb_charger *chg = power_supply_get_drvdata(psy);
switch (prop) {
+#ifdef CONFIG_MACH_LONGCHEER
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+ rc = lct_set_prop_input_suspend(chg, val);
+ break;
+#endif
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
rc = smblib_set_prop_input_suspend(chg, val);
break;
@@ -1169,6 +1278,9 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
case POWER_SUPPLY_PROP_DP_DM:
case POWER_SUPPLY_PROP_RERUN_AICL:
+#ifdef CONFIG_MACH_LONGCHEER
+ case POWER_SUPPLY_PROP_CHARGING_ENABLED:
+#endif
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
case POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED:
case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
@@ -1531,6 +1643,9 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ if ((is_poweroff_charge == false) && (stat != 0x01))
+#endif
smblib_rerun_apsd_if_required(chg);
/* clear the ICL override if it is set */
@@ -1566,6 +1681,46 @@ static int smb2_init_hw(struct smb2 *chip)
vote(chg->hvdcp_enable_votable, MICRO_USB_VOTER,
chg->micro_usb_mode, 0);
+#ifdef CONFIG_MACH_LONGCHEER
+ /* Operate the QC2.0 in 5V/9V mode i.e. Disable 12V */
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ PULSE_COUNT_QC2P0_12V | PULSE_COUNT_QC2P0_9V,
+ PULSE_COUNT_QC2P0_9V);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure QC2.0 to 9V rc=%d\n", rc);
+ return rc;
+ }
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ /* Operate the QC3.0 to limit vbus to 8.0v*/
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ PULSE_COUNT_QC3P0_MASK, 0xf);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure QC3.0 to 7.6V rc=%d\n", rc);
+ return rc;
+ }
+
+ /* lct reconfigure allowed voltage for HVDCP */
+ rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG,
+ USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't write to USBIN_ADAPTER_ALLOW_CFG rc=%d\n", rc);
+ return rc;
+ }
+#else
+ /* Operate the QC3.0 to limit vbus to 6.6v*/
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ PULSE_COUNT_QC3P0_MASK, 0x8);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure QC3.0 to 6.6V rc=%d\n", rc);
+ return rc;
+ }
+#endif
+#endif
+
/*
* AICL configuration:
* start from min and AICL ADC disable
@@ -1720,6 +1875,10 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, true, 0);
+#endif
+
switch (chip->dt.chg_inhibit_thr_mv) {
case 50:
rc = smblib_masked_write(chg, CHARGE_INHIBIT_THRESHOLD_CFG_REG,
@@ -1748,6 +1907,10 @@ static int smb2_init_hw(struct smb2 *chip)
break;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ rc = vote(chg->chg_disable_votable, DEFAULT_VOTER, false, 0);
+#endif
+
if (rc < 0) {
dev_err(chg->dev, "Couldn't configure charge inhibit threshold rc=%d\n",
rc);
@@ -2248,6 +2411,172 @@ static void smb2_create_debugfs(struct smb2 *chip)
#endif
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+static ssize_t lct_thermal_video_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", LctIsInVideo);
+}
+
+static ssize_t lct_thermal_video_status_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+
+ if (sscanf(buf, "%u", &input) != 1)
+ retval = -EINVAL;
+ else
+ LctIsInVideo = input;
+
+ pr_err("LctIsInVideo = %d\n", LctIsInVideo);
+
+ return retval;
+}
+#endif
+
+static ssize_t lct_thermal_call_status_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", LctIsInCall);
+}
+
+static ssize_t lct_thermal_call_status_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int retval;
+ unsigned int input;
+
+ if (sscanf(buf, "%u", &input) != 1)
+ retval = -EINVAL;
+ else
+ LctIsInCall = input;
+
+ pr_err("IsInCall = %d\n", LctIsInCall);
+
+ return retval;
+}
+
+static struct device_attribute attrs2[] = {
+ __ATTR(thermalcall, S_IRUGO | S_IWUSR,
+ lct_thermal_call_status_show, lct_thermal_call_status_store),
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ __ATTR(thermalvideo, S_IRUGO | S_IWUSR,
+ lct_thermal_video_status_show, lct_thermal_video_status_store),
+#endif
+};
+
+static void thermal_fb_notifier_resume_work(struct work_struct *work)
+{
+ struct smb_charger *chg = container_of(work, struct smb_charger, fb_notify_work);
+
+ LctThermal = 1;
+#if defined(CONFIG_MACH_XIAOMI_WHYRED)
+ if ((lct_backlight_off) && (LctIsInCall == 0)) {
+ if (hwc_check_india) {
+ if (lct_therm_lvl_reserved.intval >= 2)
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_india_level);
+ else
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_lvl_reserved);
+ } else {
+ if (lct_therm_lvl_reserved.intval >= 1)
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_globe_level);
+ else
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_lvl_reserved);
+ }
+ } else if (LctIsInCall)
+ smblib_set_prop_system_temp_level(chg, &lct_therm_call_level);
+ else
+ smblib_set_prop_system_temp_level(chg, &lct_therm_lvl_reserved);
+ LctThermal = 0;
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ if (LctIsInCall)
+ smblib_set_prop_system_temp_level(chg, &lct_therm_call_level);
+ else
+ smblib_set_prop_system_temp_level(chg, &lct_therm_lvl_reserved);
+ LctThermal = 0;
+#elif defined(CONFIG_MACH_XIAOMI_WAYNE)
+ if ((lct_backlight_off) && (LctIsInCall == 0)) {
+ if (lct_therm_lvl_reserved.intval >= 2)
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_globe_level);
+ else
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_level);
+ } else if (LctIsInCall == 1)
+ smblib_set_prop_system_temp_level(chg, &lct_therm_call_level);
+ else
+ smblib_set_prop_system_temp_level(chg, &lct_therm_lvl_reserved);
+ LctThermal = 0;
+#else
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (hwc_check_india == 0))
+ smblib_set_prop_system_temp_level(chg, &lct_therm_level);
+ else if ((lct_backlight_off) && (LctIsInCall == 0) &&
+ (hwc_check_india == 1)) {
+ if (lct_therm_lvl_reserved.intval >= 1)
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_india_level);
+ else
+ smblib_set_prop_system_temp_level(chg,
+ &lct_therm_level);
+ } else if (LctIsInCall)
+ smblib_set_prop_system_temp_level(chg, &lct_therm_call_level);
+ else
+ smblib_set_prop_system_temp_level(chg, &lct_therm_lvl_reserved);
+ LctThermal = 0;
+#endif
+}
+
+/* frame buffer notifier block control the suspend/resume procedure */
+static int thermal_notifier_callback(struct notifier_block *noti,
+ unsigned long event, void *data)
+{
+ struct fb_event *ev_data = data;
+ struct smb_charger *chg = container_of(noti, struct smb_charger,
+ notifier);
+ int *blank;
+
+ if (ev_data && ev_data->data && chg) {
+ blank = ev_data->data;
+ if (event == FB_EARLY_EVENT_BLANK &&
+ *blank == FB_BLANK_UNBLANK) {
+ lct_backlight_off = false;
+ schedule_work(&chg->fb_notify_work);
+ } else if (event == FB_EVENT_BLANK &&
+ *blank == FB_BLANK_POWERDOWN) {
+ lct_backlight_off = true;
+ schedule_work(&chg->fb_notify_work);
+ }
+ }
+
+ return 0;
+}
+
+static int lct_register_powermanager(struct smb_charger *chg)
+{
+#if defined(CONFIG_FB)
+ chg->notifier.notifier_call = thermal_notifier_callback;
+ fb_register_client(&chg->notifier);
+#endif
+ return 0;
+}
+
+static int lct_unregister_powermanager(struct smb_charger *chg)
+{
+#if defined(CONFIG_FB)
+ fb_unregister_client(&chg->notifier);
+#endif
+ return 0;
+}
+#endif
+#endif
+
static int smb2_probe(struct platform_device *pdev)
{
struct smb2 *chip;
@@ -2255,6 +2584,11 @@ static int smb2_probe(struct platform_device *pdev)
int rc = 0;
union power_supply_propval val;
int usb_present, batt_present, batt_health, batt_charge_type;
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ unsigned char attr_count2;
+#endif
+#endif
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -2364,6 +2698,18 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ for (attr_count2 = 0; attr_count2 < ARRAY_SIZE(attrs2); attr_count2++) {
+ rc = sysfs_create_file(&chg->dev->kobj,
+ &attrs2[attr_count2].attr);
+ if (rc < 0)
+ sysfs_remove_file(&chg->dev->kobj,
+ &attrs2[attr_count2].attr);
+ }
+#endif
+#endif
+
rc = smb2_determine_initial_status(chip);
if (rc < 0) {
pr_err("Couldn't determine initial status rc=%d\n",
@@ -2415,6 +2761,18 @@ static int smb2_probe(struct platform_device *pdev)
device_init_wakeup(chg->dev, true);
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ lct_therm_lvl_reserved.intval = 0;
+ lct_therm_level.intval = 0;
+ lct_backlight_off = false;
+ INIT_WORK(&chg->fb_notify_work, thermal_fb_notifier_resume_work);
+ /* register suspend and resume function */
+ lct_register_powermanager(chg);
+#endif
+ chg->charging_enabled = true;
+#endif
+
pr_info("QPNP SMB2 probed successfully usb:present=%d type=%d batt:present = %d health = %d charge = %d\n",
usb_present, chg->real_charger_type,
batt_present, batt_health, batt_charge_type);
@@ -2447,7 +2805,17 @@ static int smb2_remove(struct platform_device *pdev)
{
struct smb2 *chip = platform_get_drvdata(pdev);
struct smb_charger *chg = &chip->chg;
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ unsigned char attr_count2;
+ for (attr_count2 = 0; attr_count2 < ARRAY_SIZE(attrs2); attr_count2++) {
+ sysfs_remove_file(&chg->dev->kobj,
+ &attrs2[attr_count2].attr);
+ }
+ lct_unregister_powermanager(chg);
+#endif
+#endif
power_supply_unregister(chg->batt_psy);
power_supply_unregister(chg->usb_psy);
power_supply_unregister(chg->usb_port_psy);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 81623c65ea8e..3b091f78dbdf 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -25,6 +25,14 @@
#include "battery.h"
#include "step-chg-jeita.h"
#include "storm-watch.h"
+#ifdef CONFIG_MACH_LONGCHEER
+#include "fg-core.h"
+
+extern int hwc_check_global;
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+#define LCT_JEITA_CCC_AUTO_ADJUST
+#endif
+#endif
#define smblib_err(chg, fmt, ...) \
pr_err("%s: %s: " fmt, chg->name, \
@@ -341,6 +349,53 @@ static int smblib_set_opt_freq_buck(struct smb_charger *chg, int fsw_khz)
return rc;
}
+#ifdef LCT_JEITA_CCC_AUTO_ADJUST
+/*
+jeita cc COMP regiseter is 1092,please refer to qualcom doc:80_P7905_2X ,SCHG_CHGR_JEITA_CCCOMP_CFG
+qcom,thermal-mitigation = <2500000 2000000 1000000 800000 500000>;
+jeita current = fcc - JEITA_CC_COMP_CFG_IN_UEFI*1000
+*/
+
+#define JEITA_CC_COMP_CFG_IN_UEFI 1200
+static int smblib_adjust_jeita_cc_config(struct smb_charger *chg,int val_u)
+{
+ int rc= 0;
+ int current_cc_minus_ua = 0;
+
+ pr_err("smblib_adjust_jeita_cc_config fcc val_u = %d\n", val_u);
+
+ rc = smblib_get_charge_param(chg,&chg->param.jeita_cc_comp,
+ &current_cc_minus_ua);
+ pr_err("lct smblib_adjust_jeita_cc_config jeita cc current_cc_minus_ua = %d\n", current_cc_minus_ua);
+
+ if ((val_u == chg->batt_profile_fcc_ua) &&
+ (current_cc_minus_ua != JEITA_CC_COMP_CFG_IN_UEFI * 1000)) {
+ rc = smblib_set_charge_param(chg, &chg->param.jeita_cc_comp,
+ JEITA_CC_COMP_CFG_IN_UEFI * 1000);
+ pr_err("smblib_adjust_jeita_cc_config jeita cc has changed ,write it back ,write result = %d\n", rc);
+ } else if ((val_u < chg->batt_profile_fcc_ua) &&
+ ((chg->batt_profile_fcc_ua - val_u) <= JEITA_CC_COMP_CFG_IN_UEFI * 1000)) {
+ if (current_cc_minus_ua != (JEITA_CC_COMP_CFG_IN_UEFI * 1000 - (chg->batt_profile_fcc_ua - val_u))) {
+ current_cc_minus_ua = JEITA_CC_COMP_CFG_IN_UEFI * 1000 - (chg->batt_profile_fcc_ua - val_u);
+ rc = smblib_set_charge_param(chg,
+ &chg->param.jeita_cc_comp,
+ current_cc_minus_ua);
+ pr_err("smblib_adjust_jeita_cc_config jeita cc need to decrease to %d,write result = %d\n", current_cc_minus_ua,rc);
+ } else {
+ pr_err("smblib_adjust_jeita_cc_config jeita cc have decreased \n");
+ }
+ } else if ((val_u < chg->batt_profile_fcc_ua) &&
+ ((chg->batt_profile_fcc_ua - val_u) > JEITA_CC_COMP_CFG_IN_UEFI * 1000)) {
+ rc = smblib_set_charge_param(chg, &chg->param.jeita_cc_comp, 0);
+ pr_err("smblib_adjust_jeita_cc_config jeita need to set to zero,write result = %d\n", rc);
+ } else {
+ pr_err("smblib_adjust_jeita_cc_config do nothing \n");
+ }
+
+ return rc;
+}
+#endif
+
int smblib_set_charge_param(struct smb_charger *chg,
struct smb_chg_param *param, int val_u)
{
@@ -367,6 +422,10 @@ int smblib_set_charge_param(struct smb_charger *chg,
param->name, val_raw, param->reg, rc);
return rc;
}
+#ifdef LCT_JEITA_CCC_AUTO_ADJUST
+ if (strcmp(param->name,"fast charge current") == 0)
+ smblib_adjust_jeita_cc_config(chg, val_u);
+#endif
smblib_dbg(chg, PR_REGISTER, "%s = %d (0x%02x)\n",
param->name, val_u, val_raw);
@@ -494,6 +553,11 @@ static int smblib_request_dpdm(struct smb_charger *chg, bool enable)
{
int rc = 0;
+#ifdef CONFIG_MACH_LONGCHEER
+ if (chg->pr_swap_in_progress)
+ return 0;
+#endif
+
/* fetch the DPDM regulator */
if (!chg->dpdm_reg && of_get_property(chg->dev->of_node,
"dpdm-supply", NULL)) {
@@ -557,6 +621,9 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
/* if PD is active, APSD is disabled so won't have a valid result */
if (chg->pd_active) {
chg->real_charger_type = POWER_SUPPLY_TYPE_USB_PD;
+#ifdef CONFIG_MACH_LONGCHEER
+ chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
+#endif
} else {
/*
* Update real charger type only if its not FLOAT
@@ -564,7 +631,14 @@ static const struct apsd_result *smblib_update_usb_type(struct smb_charger *chg)
*/
if (!(apsd_result->pst == POWER_SUPPLY_TYPE_USB_FLOAT &&
chg->real_charger_type == POWER_SUPPLY_TYPE_USB))
+#ifdef CONFIG_MACH_LONGCHEER
+ {
+#endif
chg->real_charger_type = apsd_result->pst;
+#ifdef CONFIG_MACH_LONGCHEER
+ chg->usb_psy_desc.type = apsd_result->pst;
+ }
+#endif
}
smblib_dbg(chg, PR_MISC, "APSD=%s PD=%d\n",
@@ -1171,6 +1245,9 @@ static int smblib_hvdcp_hw_inov_dis_vote_callback(struct votable *votable,
struct smb_charger *chg = data;
int rc;
+#if defined(CONFIG_MACH_XIAOMI_WAYNE) || defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ disable = 0;
+#endif
if (disable) {
/*
* the pulse count register get zeroed when autonomous mode is
@@ -1580,6 +1657,9 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
bool usb_online, dc_online, qnovo_en;
u8 stat, pt_en_cmd;
int rc;
+#ifdef CONFIG_MACH_LONGCHEER
+ int batt_health;
+#endif
rc = smblib_get_prop_usb_online(chg, &pval);
if (rc < 0) {
@@ -1597,6 +1677,16 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
}
dc_online = (bool)pval.intval;
+#ifdef CONFIG_MACH_LONGCHEER
+ rc = smblib_get_prop_batt_health(chg, &pval);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get batt health property rc=%d\n",
+ rc);
+ return rc;
+ }
+ batt_health = pval.intval;
+#endif
+
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
@@ -1638,6 +1728,15 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
break;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ if ((POWER_SUPPLY_HEALTH_WARM == batt_health ||
+ POWER_SUPPLY_HEALTH_OVERHEAT == batt_health) &&
+ (val->intval == POWER_SUPPLY_STATUS_FULL)) {
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ return 0;
+ }
+#endif
+
if (val->intval != POWER_SUPPLY_STATUS_CHARGING)
return 0;
@@ -1825,6 +1924,23 @@ int smblib_get_prop_from_bms(struct smb_charger *chg,
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+int smblib_get_prop_battery_full_design(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ struct fg_chip *chip;
+
+ if (!chg->bms_psy)
+ return -EINVAL;
+ chip = power_supply_get_drvdata(chg->bms_psy);
+ if (chip->battery_full_design)
+ val->intval = chip->battery_full_design;
+ else
+ val->intval = 4000;
+ return 0;
+}
+#endif
+
/***********************
* BATTERY PSY SETTERS *
***********************/
@@ -1853,6 +1969,31 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg,
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+int lct_set_prop_input_suspend(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc = 0;
+ union power_supply_propval pval = {0, };
+
+ pr_err("[%s] val=%d\n", __func__, val->intval);
+ if (val->intval) {
+ pval.intval = 0;
+ smblib_set_prop_input_suspend(chg, &pval);
+ } else {
+ pval.intval = 1;
+ chg->pl_psy = power_supply_get_by_name("parallel");
+ if (chg->pl_psy) {
+ power_supply_set_property(chg->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+ }
+ smblib_set_prop_input_suspend(chg, &pval);
+ }
+ power_supply_changed(chg->batt_psy);
+ return rc;
+}
+#endif
+
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
const union power_supply_propval *val)
{
@@ -1863,6 +2004,18 @@ int smblib_set_prop_batt_capacity(struct smb_charger *chg,
return 0;
}
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+extern union power_supply_propval lct_therm_lvl_reserved;
+extern bool lct_backlight_off;
+extern int LctIsInCall;
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+extern int LctIsInVideo;
+#endif
+extern int LctThermal;
+extern int hwc_check_india;
+#endif
+#endif
int smblib_set_prop_system_temp_level(struct smb_charger *chg,
const union power_supply_propval *val)
{
@@ -1875,8 +2028,66 @@ int smblib_set_prop_system_temp_level(struct smb_charger *chg,
if (val->intval > chg->thermal_levels)
return -EINVAL;
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ pr_err("smblib_set_prop_system_temp_level val=%d, chg->system_temp_level=%d, LctThermal=%d, lct_backlight_off= %d, IsInCall=%d, hwc_check_india=%d\n ",
+ val->intval,chg->system_temp_level, LctThermal, lct_backlight_off, LctIsInCall, hwc_check_india);
+
+ if (LctThermal == 0)
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ if (val->intval < 6)
+#endif
+ lct_therm_lvl_reserved.intval = val->intval;
+#if defined(CONFIG_MACH_XIAOMI_WHYRED)
+ if (hwc_check_india) {
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 2))
+ return 0;
+ } else {
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 1))
+ return 0;
+ }
+#elif defined(CONFIG_MACH_XIAOMI_WAYNE)
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 2))
+ return 0;
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 3))
+ return 0;
+#else
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 0) && (hwc_check_india == 0))
+ return 0;
+ if ((lct_backlight_off) && (LctIsInCall == 0) && (val->intval > 1) && (hwc_check_india == 1))
+ return 0;
+#endif
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_WAYNE)
+ if ((LctIsInCall == 1) && (val->intval != 4))
+ return 0;
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ if ((LctIsInCall == 1) && (val->intval != 5))
+ return 0;
+#endif
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ if ((LctIsInVideo == 1) && (val->intval != 6) && (lct_backlight_off == 0) && (hwc_check_india == 1))
+ return 0;
+#endif
+ if (val->intval == chg->system_temp_level)
+ return 0;
+#endif
+#endif
+
chg->system_temp_level = val->intval;
/* disable parallel charge in case of system temp level */
+#ifdef CONFIG_MACH_LONGCHEER
+ if ((lct_backlight_off == 0) && (chg->system_temp_level <= 1))
+ vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,false,0);
+#if defined(CONFIG_MACH_XIAOMI_WHYRED)
+ else if ((hwc_check_india == 0) && (chg->system_temp_level <= 2))
+ vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,false,0);
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ else if (chg->system_temp_level <= 2)
+ vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,false,0);
+#endif
+ else
+#endif
vote(chg->pl_disable_votable, THERMAL_DAEMON_VOTER,
chg->system_temp_level ? true : false, 0);
@@ -1988,6 +2199,13 @@ static int smblib_force_vbus_voltage(struct smb_charger *chg, u8 val)
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+#define MAX_PLUSE_COUNT_ALLOWED 15
+#else
+#define MAX_PLUSE_COUNT_ALLOWED 8
+#endif
+#endif
int smblib_dp_dm(struct smb_charger *chg, int val)
{
int target_icl_ua, rc = 0;
@@ -1995,6 +2213,10 @@ int smblib_dp_dm(struct smb_charger *chg, int val)
switch (val) {
case POWER_SUPPLY_DP_DM_DP_PULSE:
+#ifdef CONFIG_MACH_LONGCHEER
+ if (chg->pulse_cnt >= MAX_PLUSE_COUNT_ALLOWED)
+ return rc;
+#endif
rc = smblib_dp_pulse(chg);
if (!rc)
chg->pulse_cnt++;
@@ -2071,7 +2293,9 @@ int smblib_disable_hw_jeita(struct smb_charger *chg, bool disable)
* Disable h/w base JEITA compensation if s/w JEITA is enabled
*/
mask = JEITA_EN_COLD_SL_FCV_BIT
+#ifndef CONFIG_MACH_LONGCHEER
| JEITA_EN_HOT_SL_FCV_BIT
+#endif
| JEITA_EN_HOT_SL_CCC_BIT
| JEITA_EN_COLD_SL_CCC_BIT,
rc = smblib_masked_write(chg, JEITA_EN_CFG_REG, mask,
@@ -2219,6 +2443,14 @@ int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val)
{
+#ifdef CONFIG_MACH_LONGCHEER
+ int rc = 0;
+
+ rc = smblib_get_prop_usb_present(chg, val);
+ if (rc < 0 || !val->intval)
+ return rc;
+#endif
+
if (!chg->iio.usbin_v_chan ||
PTR_ERR(chg->iio.usbin_v_chan) == -EPROBE_DEFER)
chg->iio.usbin_v_chan = iio_channel_get(chg->dev, "usbin_v");
@@ -2485,8 +2717,18 @@ int smblib_get_prop_die_health(struct smb_charger *chg,
#define SDP_CURRENT_UA 500000
#define CDP_CURRENT_UA 1500000
+#ifdef CONFIG_MACH_LONGCHEER
+#define DCP_CURRENT_UA 2000000
+#define HVDCP2_CURRENT_UA 1500000
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+#define HVDCP_CURRENT_UA 2000000
+#else
+#define HVDCP_CURRENT_UA 2900000
+#endif
+#else
#define DCP_CURRENT_UA 1500000
#define HVDCP_CURRENT_UA 3000000
+#endif
#define TYPEC_DEFAULT_CURRENT_UA 900000
#define TYPEC_MEDIUM_CURRENT_UA 1500000
#define TYPEC_HIGH_CURRENT_UA 3000000
@@ -2525,6 +2767,13 @@ int smblib_set_prop_pd_current_max(struct smb_charger *chg,
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+#define FLOAT_CURRENT_UA 500000
+#else
+#define FLOAT_CURRENT_UA 1000000
+#endif
+#endif
static int smblib_handle_usb_current(struct smb_charger *chg,
int usb_current)
{
@@ -2537,7 +2786,11 @@ static int smblib_handle_usb_current(struct smb_charger *chg,
* of Rp
*/
typec_mode = smblib_get_prop_typec_mode(chg);
+#ifdef CONFIG_MACH_LONGCHEER
+ rp_ua = FLOAT_CURRENT_UA;
+#else
rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+#endif
rc = vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER,
true, rp_ua);
if (rc < 0)
@@ -2584,6 +2837,18 @@ int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+int smblib_set_prop_rerun_apsd(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ if (val->intval == 1) {
+ chg->float_rerun_apsd = true;
+ smblib_rerun_apsd(chg);
+ }
+ return 0;
+}
+#endif
+
int smblib_set_prop_boost_current(struct smb_charger *chg,
const union power_supply_propval *val)
{
@@ -3060,11 +3325,27 @@ int smblib_get_charge_current(struct smb_charger *chg,
typec_source_rd = smblib_get_prop_ufp_mode(chg);
+#ifdef CONFIG_MACH_LONGCHEER
+ /* QC 3.0 adapter */
+ if (apsd_result->bit & QC_3P0_BIT) {
+ *total_current_ua = HVDCP_CURRENT_UA;
+ pr_info("QC3.0 set icl to 2.9A\n");
+ return 0;
+ }
+
+ /* QC 2.0 adapter */
+ if (apsd_result->bit & QC_2P0_BIT) {
+ *total_current_ua = HVDCP2_CURRENT_UA;
+ pr_info("QC2.0 set icl to 1.5A\n");
+ return 0;
+ }
+#else
/* QC 2.0/3.0 adapter */
if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
*total_current_ua = HVDCP_CURRENT_UA;
return 0;
}
+#endif
if (non_compliant) {
switch (apsd_result->bit) {
@@ -3238,6 +3519,11 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data)
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
struct storm_watch *wdata;
+#ifdef CONFIG_MACH_LONGCHEER
+ const struct apsd_result *apsd = smblib_get_apsd_result(chg);
+ int rc;
+ u8 stat = 0, max_pulses = 0;
+#endif
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
if (!chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data)
@@ -3245,6 +3531,44 @@ irqreturn_t smblib_handle_usbin_uv(int irq, void *data)
wdata = &chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data->storm_data;
reset_storm_count(wdata);
+#ifdef CONFIG_MACH_LONGCHEER
+ if (!chg->non_compliant_chg_detected &&
+ apsd->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ rc = smblib_read(chg, QC_CHANGE_STATUS_REG, &stat);
+ if (rc < 0)
+ smblib_err(chg,
+ "Couldn't read CHANGE_STATUS_REG rc=%d\n", rc);
+
+ if (stat & QC_5V_BIT)
+ return IRQ_HANDLED;
+
+ rc = smblib_read(chg, HVDCP_PULSE_COUNT_MAX_REG, &max_pulses);
+ if (rc < 0)
+ smblib_err(chg,
+ "Couldn't read QC2 max pulses rc=%d\n", rc);
+
+ chg->non_compliant_chg_detected = true;
+ chg->qc2_max_pulses = (max_pulses &
+ HVDCP_PULSE_COUNT_MAX_QC2_MASK);
+
+ if (stat & QC_12V_BIT) {
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ HVDCP_PULSE_COUNT_MAX_QC2_MASK,
+ HVDCP_PULSE_COUNT_MAX_QC2_9V);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't force max pulses to 9V rc=%d\n",
+ rc);
+ } else if (stat & QC_9V_BIT) {
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ HVDCP_PULSE_COUNT_MAX_QC2_MASK,
+ HVDCP_PULSE_COUNT_MAX_QC2_5V);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't force max pulses to 5V rc=%d\n",
+ rc);
+ }
+ smblib_rerun_apsd(chg);
+ }
+#endif
return IRQ_HANDLED;
}
@@ -3308,6 +3632,9 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
bool vbus_rising;
struct smb_irq_data *data;
struct storm_watch *wdata;
+#ifdef CONFIG_MACH_LONGCHEER
+ union power_supply_propval pval = {1, };
+#endif
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
@@ -3325,6 +3652,12 @@ void smblib_usb_plugin_locked(struct smb_charger *chg)
smblib_err(chg, "Couldn't to enable DPDM rc=%d\n", rc);
if (chg->fcc_stepper_mode)
vote(chg->fcc_votable, FCC_STEPPER_VOTER, false, 0);
+#ifdef CONFIG_MACH_LONGCHEER
+ chg->pl_psy = power_supply_get_by_name("parallel");
+ if (chg->pl_psy)
+ power_supply_set_property(chg->pl_psy,
+ POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
+#endif
/* Schedule work to enable parallel charger */
vote(chg->awake_votable, PL_DELAY_VOTER, true, 0);
schedule_delayed_work(&chg->pl_enable_work,
@@ -3625,13 +3958,23 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
*/
if (!is_client_vote_enabled(chg->usb_icl_votable,
USB_PSY_VOTER))
+#ifdef CONFIG_MACH_LONGCHEER
+ vote(chg->usb_icl_votable, USB_PSY_VOTER, true, 500000);
+#else
vote(chg->usb_icl_votable, USB_PSY_VOTER, true, 100000);
+#endif
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, false, 0);
break;
case POWER_SUPPLY_TYPE_USB_CDP:
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ vote(chg->usb_icl_votable, USER_VOTER, false, 0);
+#endif
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
break;
case POWER_SUPPLY_TYPE_USB_DCP:
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ vote(chg->usb_icl_votable, USER_VOTER, false, 0);
+#endif
typec_mode = smblib_get_prop_typec_mode(chg);
rp_ua = get_rp_based_dcp_current(chg, typec_mode);
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
@@ -3641,11 +3984,42 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
* limit ICL to 100mA, the USB driver will enumerate to check
* if this is a SDP and appropriately set the current
*/
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ vote(chg->usb_icl_votable, USER_VOTER, false, 0);
+#endif
+#ifdef CONFIG_MACH_XIAOMI_WHYRED
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 500000);
+#else
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1000000);
+#endif
+#else
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 100000);
+#endif
break;
case POWER_SUPPLY_TYPE_USB_HVDCP:
+#ifdef CONFIG_MACH_LONGCHEER
+#if defined(CONFIG_MACH_XIAOMI_TULIP)
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 2000000);
+#elif defined(CONFIG_MACH_XIAOMI_WAYNE)
+ vote(chg->usb_icl_votable, USER_VOTER, true, 1500000);
+#else
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
+#endif
+ break;
+#endif
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
+#if defined(CONFIG_MACH_XIAOMI_WHYRED) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 2000000);
+#elif defined(CONFIG_MACH_XIAOMI_WAYNE)
+ vote(chg->usb_icl_votable, USER_VOTER, false, 0);
+ if (hwc_check_global)
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 2300000);
+ else
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 2900000);
+#else
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 3000000);
+#endif
break;
default:
smblib_err(chg, "Unknown APSD %d; forcing 500mA\n", pst);
@@ -3684,13 +4058,22 @@ static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
const struct apsd_result *apsd_result;
+#ifdef CONFIG_MACH_LONGCHEER
+ union power_supply_propval pval = {0, };
+ int usb_present = 0, rc = 0;
+#endif
if (!rising)
return;
apsd_result = smblib_update_usb_type(chg);
+#ifdef CONFIG_MACH_LONGCHEER
+ if ((!chg->typec_legacy_valid) ||
+ (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP_3))
+#else
if (!chg->typec_legacy_valid)
+#endif
smblib_force_legacy_icl(chg, apsd_result->pst);
switch (apsd_result->bit) {
@@ -3716,10 +4099,55 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
break;
}
+#ifdef CONFIG_MACH_LONGCHEER
+ if (chg->float_rerun_apsd) {
+ smblib_err(chg, "rerun apsd for float type\n");
+ rc = smblib_get_prop_usb_present(chg, &pval);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get usb present rc = %d\n", rc);
+ return;
+ }
+ usb_present = pval.intval;
+ if (!usb_present)
+ return;
+ if (apsd_result->bit & QC_2P0_BIT) {
+ pval.intval = 0;
+ smblib_set_prop_pd_active(chg, &pval);
+ chg->float_rerun_apsd = false;
+ } else if (apsd_result->bit & FLOAT_CHARGER_BIT) {
+#if defined(CONFIG_MACH_XIAOMI_WAYNE) || defined(CONFIG_MACH_XIAOMI_TULIP)
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true,
+ 1000000);
+#else
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true,
+ 500000);
+#endif
+ chg->float_rerun_apsd = false;
+ smblib_err(chg, "rerun apsd still float\n");
+ }
+ }
+#endif
+
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
apsd_result->name);
}
+#ifdef CONFIG_MACH_LONGCHEER
+bool smblib_check_charge_type(struct smb_charger *chg )
+{
+ bool ret = false;
+ const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
+ enum power_supply_type real_charger_type = apsd_result->pst;
+
+ smblib_dbg(chg, PR_REGISTER, "real_charger_type = 0x%02x\n",
+ real_charger_type);
+ if (POWER_SUPPLY_TYPE_USB <= real_charger_type &&
+ POWER_SUPPLY_TYPE_USB_PD >= real_charger_type)
+ ret = true;
+ return ret;
+}
+#endif
+
irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
@@ -3735,6 +4163,9 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
if (chg->micro_usb_mode && (stat & APSD_DTC_STATUS_DONE_BIT)
+#ifdef CONFIG_MACH_LONGCHEER
+ && !smblib_check_charge_type(chg)
+#endif
&& !chg->uusb_apsd_rerun_done) {
/*
* Force re-run APSD to handle slow insertion related
@@ -3808,7 +4239,11 @@ static int typec_try_sink(struct smb_charger *chg)
* give opportunity to the other side to be a SRC,
* for tDRPTRY + Tccdebounce time
*/
+#ifdef CONFIG_MACH_LONGCHEER
+ msleep(100);
+#else
msleep(120);
+#endif
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
@@ -3885,7 +4320,11 @@ try_wait_src:
}
/* Need to be in this state for tDRPTRY time, 75ms~150ms */
+#ifdef CONFIG_MACH_LONGCHEER
+ msleep(150);
+#else
msleep(80);
+#endif
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
@@ -4023,6 +4462,9 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
chg->pd_active = 0;
chg->pd_hard_reset = 0;
chg->typec_legacy_valid = false;
+#ifdef CONFIG_MACH_LONGCHEER
+ chg->float_rerun_apsd = false;
+#endif
/* write back the default FLOAT charger configuration */
rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
@@ -4036,6 +4478,19 @@ static void smblib_handle_typec_removal(struct smb_charger *chg)
if (rc < 0)
smblib_err(chg, "Couldn't set 120mS tCC debounce rc=%d\n", rc);
+#ifdef CONFIG_MACH_LONGCHEER
+ /* if non-compliant charger caused UV, restore original max pulses */
+ if (chg->non_compliant_chg_detected) {
+ rc = smblib_masked_write(chg, HVDCP_PULSE_COUNT_MAX_REG,
+ HVDCP_PULSE_COUNT_MAX_QC2_MASK,
+ chg->qc2_max_pulses);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't restore max pulses rc=%d\n",
+ rc);
+ chg->non_compliant_chg_detected = false;
+ }
+#endif
+
/* enable APSD CC trigger for next insertion */
rc = smblib_masked_write(chg, TYPE_C_CFG_REG,
APSD_START_ON_CC_BIT, APSD_START_ON_CC_BIT);
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5ca5e923e651..8bb9887b5108 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -69,6 +69,9 @@ enum print_reason {
#define OV_VOTER "OV_VOTER"
#define FCC_STEPPER_VOTER "FCC_STEPPER_VOTER"
+#ifdef CONFIG_MACH_LONGCHEER
+#define THERMAL_CONFIG_FB 1
+#endif
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
#define BOOST_BACK_STORM_COUNT 3
@@ -265,6 +268,9 @@ struct smb_charger {
struct power_supply *usb_main_psy;
struct power_supply *usb_port_psy;
enum power_supply_type real_charger_type;
+#ifdef CONFIG_MACH_LONGCHEER
+ struct power_supply *pl_psy;
+#endif
/* notifiers */
struct notifier_block nb;
@@ -323,6 +329,9 @@ struct smb_charger {
int dcp_icl_ua;
int fake_capacity;
bool step_chg_enabled;
+#ifdef CONFIG_MACH_LONGCHEER
+ int charging_enabled;
+#endif
bool sw_jeita_enabled;
bool is_hdc;
bool chg_done;
@@ -348,14 +357,27 @@ struct smb_charger {
bool use_extcon;
bool otg_present;
bool fcc_stepper_mode;
+#ifdef CONFIG_MACH_LONGCHEER
+#ifdef THERMAL_CONFIG_FB
+ struct notifier_block notifier;
+ struct work_struct fb_notify_work;
+#endif
+#endif
/* workaround flag */
u32 wa_flags;
bool cc2_detach_wa_active;
bool typec_en_dis_active;
+#ifdef CONFIG_MACH_LONGCHEER
+ bool float_rerun_apsd;
+#endif
bool try_sink_active;
int boost_current_ua;
int temp_speed_reading_count;
+#ifdef CONFIG_MACH_LONGCHEER
+ int qc2_max_pulses;
+ bool non_compliant_chg_detected;
+#endif
/* extcon for VBUS / ID notification to USB for uUSB */
struct extcon_dev *extcon;
@@ -436,6 +458,10 @@ int smblib_get_prop_input_current_limited(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
+#ifdef CONFIG_MACH_LONGCHEER
+int lct_set_prop_input_suspend(struct smb_charger *chg,
+ const union power_supply_propval *val);
+#endif
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_system_temp_level(struct smb_charger *chg,
@@ -527,7 +553,13 @@ int smblib_get_prop_from_bms(struct smb_charger *chg,
int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
const union power_supply_propval *val);
void smblib_usb_typec_change(struct smb_charger *chg);
+#ifdef CONFIG_MACH_LONGCHEER
+int smblib_get_prop_battery_full_design(struct smb_charger *chg,
+ union power_supply_propval *val);
+int smblib_set_prop_rerun_apsd(struct smb_charger *chg,
+ const union power_supply_propval *val);
+#endif
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
diff --git a/drivers/power/supply/qcom/smb-reg.h b/drivers/power/supply/qcom/smb-reg.h
index 4ddb085e9300..6eaf32d971f7 100644
--- a/drivers/power/supply/qcom/smb-reg.h
+++ b/drivers/power/supply/qcom/smb-reg.h
@@ -586,7 +586,21 @@ enum {
#define EN_TRYSINK_MODE_BIT BIT(2)
#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1)
#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0)
+#ifdef CONFIG_MACH_LONGCHEER
+#define HVDCP_PULSE_COUNT_MAX_REG (USBIN_BASE + 0x5B)
+#define HVDCP_PULSE_COUNT_MAX_QC2_MASK GENMASK(7, 6)
+enum {
+ HVDCP_PULSE_COUNT_MAX_QC2_5V,
+ HVDCP_PULSE_COUNT_MAX_QC2_9V,
+ HVDCP_PULSE_COUNT_MAX_QC2_12V,
+ HVDCP_PULSE_COUNT_MAX_QC2_INVALID
+};
+
+#define PULSE_COUNT_QC2P0_12V BIT(7)
+#define PULSE_COUNT_QC2P0_9V BIT(6)
+#define PULSE_COUNT_QC3P0_MASK GENMASK(5, 0)
+#endif
#define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60)
#define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0)
enum {
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index 55852a1ef9bd..1ffaa5a4a8df 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -704,7 +704,9 @@ static int smb1351_fastchg_current_set(struct smb1351_charger *chip,
(fastchg_current > SMB1351_CHG_FAST_MAX_MA)) {
pr_err("bad pre_fastchg current mA=%d asked to set\n",
fastchg_current);
+#ifndef CONFIG_MACH_LONGCHEER
return -EINVAL;
+#endif
}
/*
@@ -1429,7 +1431,9 @@ static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip,
if (chip->parallel_charger_suspended == suspend) {
pr_debug("Skip same state request suspended = %d suspend=%d\n",
chip->parallel_charger_suspended, !suspend);
+#ifndef CONFIG_MACH_LONGCHEER
return 0;
+#endif
}
if (!suspend) {
@@ -1523,6 +1527,17 @@ static int smb1351_parallel_set_chg_suspend(struct smb1351_charger *chip,
}
chip->parallel_charger_suspended = false;
} else {
+#ifdef CONFIG_MACH_LONGCHEER
+ smb1351_enable_volatile_writes(chip);
+ /* control USB suspend via command bits */
+ rc = smb1351_masked_write(chip, VARIOUS_FUNC_REG,
+ APSD_EN_BIT | SUSPEND_MODE_CTRL_BIT,
+ SUSPEND_MODE_CTRL_BY_I2C);
+ if (rc) {
+ pr_err("Couldn't set USB suspend rc=%d\n", rc);
+ return rc;
+ }
+#endif
rc = smb1351_usb_suspend(chip, CURRENT, true);
if (rc)
pr_debug("failed to suspend rc=%d\n", rc);
@@ -3166,6 +3181,9 @@ fail_smb1351_regulator_init:
return rc;
}
+#ifdef CONFIG_MACH_LONGCHEER
+extern int hwc_check_global;
+#endif
static int smb1351_parallel_charger_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -3185,6 +3203,13 @@ static int smb1351_parallel_charger_probe(struct i2c_client *client,
chip->parallel_charger = true;
chip->parallel_charger_suspended = true;
+#ifdef CONFIG_MACH_LONGCHEER
+ if (hwc_check_global) {
+ pr_err("Global hasn't smb1350 ragulator,return\n");
+ return -ENODEV;
+ }
+#endif
+
chip->usb_suspended_status = of_property_read_bool(node,
"qcom,charging-disabled");
rc = of_property_read_u32(node, "qcom,float-voltage-mv",
@@ -3355,8 +3380,29 @@ static struct i2c_driver smb1351_charger_driver = {
.id_table = smb1351_charger_id,
};
-module_i2c_driver(smb1351_charger_driver);
+#ifdef CONFIG_MACH_LONGCHEER
+static int __init smb1351_charger_init(void)
+{
+ struct power_supply *pl_psy = power_supply_get_by_name("parallel");
+
+ if (pl_psy) {
+ pr_info("Another parallel driver has been registered\n");
+ return -ENOENT;
+ }
+
+ return i2c_add_driver(&smb1351_charger_driver);
+}
+static void __exit smb1351_charger_exit(void)
+{
+ i2c_del_driver(&smb1351_charger_driver);
+}
+
+late_initcall(smb1351_charger_init);
+module_exit(smb1351_charger_exit);
+#else
+module_i2c_driver(smb1351_charger_driver);
+#endif
MODULE_DESCRIPTION("smb1351 Charger");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("i2c:smb1351-charger");
diff --git a/drivers/power/supply/qcom/step-chg-jeita.c b/drivers/power/supply/qcom/step-chg-jeita.c
index f6b7be5ba094..c319799d87af 100644
--- a/drivers/power/supply/qcom/step-chg-jeita.c
+++ b/drivers/power/supply/qcom/step-chg-jeita.c
@@ -118,25 +118,59 @@ static struct step_chg_cfg step_chg_config = {
static struct jeita_fcc_cfg jeita_fcc_config = {
.psy_prop = POWER_SUPPLY_PROP_TEMP,
.prop_name = "BATT_TEMP",
+#ifdef CONFIG_MACH_LONGCHEER
+ .hysteresis = 0, /* 1degC hysteresis */
+#else
.hysteresis = 10, /* 1degC hysteresis */
+#endif
.fcc_cfg = {
/* TEMP_LOW TEMP_HIGH FCC */
+#ifdef CONFIG_MACH_LONGCHEER
+#if defined(CONFIG_MACH_XIAOMI_WAYNE)
+ {0, 50, 300000},
+ {51, 150, 900000},
+ {151, 450, 2900000},
+ {451, 600, 1500000},
+#elif defined(CONFIG_MACH_XIAOMI_WHYRED)
+ {0, 50, 400000},
+ {51, 150, 1200000},
+ {151, 450, 2500000},
+ {451, 600, 1200000},
+#elif defined(CONFIG_MACH_XIAOMI_TULIP)
+ {0, 50, 400000},
+ {51, 150, 1200000},
+ {151, 450, 2500000},
+ {451, 600, 2000000},
+#endif
+#else
{0, 100, 600000},
{101, 200, 2000000},
{201, 450, 3000000},
{451, 550, 600000},
+#endif
},
};
static struct jeita_fv_cfg jeita_fv_config = {
.psy_prop = POWER_SUPPLY_PROP_TEMP,
.prop_name = "BATT_TEMP",
+#ifdef CONFIG_MACH_LONGCHEER
+ .hysteresis = 0, /* 1degC hysteresis */
+#else
.hysteresis = 10, /* 1degC hysteresis */
+#endif
.fv_cfg = {
+#ifdef CONFIG_MACH_LONGCHEER
+ /* TEMP_LOW TEMP_HIGH FV */
+ {0, 150, 4400000},
+ {151, 450, 4400000},
+ {451, 600, 4100000},
+#else
/* TEMP_LOW TEMP_HIGH FCC */
{0, 100, 4200000},
{101, 450, 4400000},
{451, 550, 4200000},
+#endif
},
};
@@ -266,11 +300,36 @@ reschedule:
return (STEP_CHG_HYSTERISIS_DELAY_US - elapsed_us + 1000);
}
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+extern union power_supply_propval lct_therm_lvl_reserved;
+extern int LctIsInVideo;
+extern int hwc_check_india;
+union power_supply_propval lct_therm_video_level = {6,};
+#endif
+
static int handle_jeita(struct step_chg_info *chip)
{
union power_supply_propval pval = {0, };
int rc = 0, fcc_ua = 0, fv_uv = 0;
u64 elapsed_us;
+#ifdef CONFIG_MACH_LONGCHEER
+ int temp = 1;
+#endif
+
+#ifdef CONFIG_MACH_XIAOMI_WAYNE
+ if (hwc_check_india) {
+ pr_err("lct video LctIsInVideo=%d, lct_therm_lvl_reserved=%d\n",
+ LctIsInVideo, lct_therm_lvl_reserved.intval);
+ if (LctIsInVideo)
+ rc = power_supply_set_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
+ &lct_therm_video_level);
+ else
+ rc = power_supply_set_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
+ &lct_therm_lvl_reserved);
+ }
+#endif
rc = power_supply_get_property(chip->batt_psy,
POWER_SUPPLY_PROP_SW_JEITA_ENABLED, &pval);
@@ -297,6 +356,10 @@ static int handle_jeita(struct step_chg_info *chip)
pr_err("Couldn't read %s property rc=%d\n",
step_chg_config.prop_name, rc);
return rc;
+#ifdef CONFIG_MACH_LONGCHEER
+ } else {
+ temp = pval.intval;
+#endif
}
rc = get_val(jeita_fcc_config.fcc_cfg, jeita_fcc_config.hysteresis,
@@ -319,6 +382,11 @@ static int handle_jeita(struct step_chg_info *chip)
vote(chip->fcc_votable, JEITA_VOTER, true, fcc_ua);
+#ifdef CONFIG_MACH_XIAOMI_TULIP
+ if ((temp < 0) || (temp > 600))
+ vote(chip->fcc_votable, JEITA_VOTER, true, 0);
+#endif
+
rc = get_val(jeita_fv_config.fv_cfg, jeita_fv_config.hysteresis,
chip->jeita_fv_index,
pval.intval,
diff --git a/include/linux/input/qpnp-power-on.h b/include/linux/input/qpnp-power-on.h
index 5944f0fd3414..179b1d5de323 100644
--- a/include/linux/input/qpnp-power-on.h
+++ b/include/linux/input/qpnp-power-on.h
@@ -62,6 +62,10 @@ enum pon_restart_reason {
/* 32 ~ 63 for OEMs/ODMs secific features */
PON_RESTART_REASON_OEM_MIN = 0x20,
+#ifdef CONFIG_MACH_LONGCHEER
+ PON_RESTART_REASON_PANIC = 0x21,
+ PON_RESTART_REASON_NORMAL = 0x22,
+#endif
PON_RESTART_REASON_OEM_MAX = 0x3f,
};
@@ -72,6 +76,10 @@ int qpnp_pon_trigger_config(enum pon_trigger_source pon_src, bool enable);
int qpnp_pon_wd_config(bool enable);
int qpnp_pon_set_restart_reason(enum pon_restart_reason reason);
bool qpnp_pon_check_hard_reset_stored(void);
+#ifdef CONFIG_MACH_LONGCHEER
+int qpnp_pon_is_lpk(void);
+#endif
+int qpnp_pon_is_ps_hold_reset(void);
#else
static int qpnp_pon_system_pwr_off(enum pon_power_off_type type)
@@ -96,6 +104,16 @@ static inline bool qpnp_pon_check_hard_reset_stored(void)
{
return false;
}
+#ifdef CONFIG_MACH_LONGCHEER
+static inline int qpnp_pon_is_lpk(void)
+{
+ return -ENODEV;
+}
+static inline int qpnp_pon_is_ps_hold_reset(void)
+{
+ return -ENODEV;
+}
+#endif
#endif
#endif
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 2ebd54c98e61..e2fcf8128b85 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -275,6 +275,10 @@ enum power_supply_property {
POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE,
POWER_SUPPLY_PROP_PARALLEL_FCC_MAX,
POWER_SUPPLY_PROP_MIN_ICL,
+#ifdef CONFIG_MACH_LONGCHEER
+ POWER_SUPPLY_PROP_FG_RESET_CLOCK,
+ POWER_SUPPLY_PROP_RERUN_APSD,
+#endif
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */