diff options
-rw-r--r-- | drivers/power/power_supply_sysfs.c | 7 | ||||
-rw-r--r-- | drivers/power/reset/msm-poweroff.c | 11 | ||||
-rw-r--r-- | drivers/power/supply/qcom/battery.c | 94 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-core.h | 9 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-memif.c | 60 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-reg.h | 27 | ||||
-rw-r--r-- | drivers/power/supply/qcom/fg-util.c | 8 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-fg-gen3.c | 309 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-smb2.c | 368 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.c | 455 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-lib.h | 32 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb-reg.h | 14 | ||||
-rw-r--r-- | drivers/power/supply/qcom/smb1351-charger.c | 48 | ||||
-rw-r--r-- | drivers/power/supply/qcom/step-chg-jeita.c | 68 | ||||
-rw-r--r-- | include/linux/input/qpnp-power-on.h | 18 | ||||
-rw-r--r-- | include/linux/power_supply.h | 4 |
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, + ¤t_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 *' */ |