diff options
Diffstat (limited to 'drivers/power')
-rw-r--r-- | drivers/power/reset/msm-poweroff.c | 2 | ||||
-rw-r--r-- | drivers/power/supply/qcom/pmic-voter.c | 2 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-fg.c | 105 | ||||
-rw-r--r-- | drivers/power/supply/qcom/qpnp-smbcharger.c | 137 |
4 files changed, 223 insertions, 23 deletions
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c index 50b5d76d7df0..f267ec9d80c0 100644 --- a/drivers/power/reset/msm-poweroff.c +++ b/drivers/power/reset/msm-poweroff.c @@ -84,7 +84,7 @@ static struct notifier_block panic_blk = { #endif static int dload_type = SCM_DLOAD_FULLDUMP; -static int download_mode = 1; +static int download_mode; static struct kobject dload_kobj; static void *dload_mode_addr, *dload_type_addr; static bool dload_mode_enabled; diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c index 3d0a71844608..c107c82286cf 100644 --- a/drivers/power/supply/qcom/pmic-voter.c +++ b/drivers/power/supply/qcom/pmic-voter.c @@ -20,7 +20,7 @@ #include <linux/pmic-voter.h> -#define NUM_MAX_CLIENTS 16 +#define NUM_MAX_CLIENTS 10 #define DEBUG_FORCE_CLIENT "DEBUG_FORCE_CLIENT" static DEFINE_SPINLOCK(votable_list_slock); diff --git a/drivers/power/supply/qcom/qpnp-fg.c b/drivers/power/supply/qcom/qpnp-fg.c index 1ace44f121b4..2f5b9e47aba2 100644 --- a/drivers/power/supply/qcom/qpnp-fg.c +++ b/drivers/power/supply/qcom/qpnp-fg.c @@ -239,18 +239,25 @@ enum fg_mem_data_index { static struct fg_mem_setting settings[FG_MEM_SETTING_MAX] = { /* ID Address, Offset, Value*/ - SETTING(SOFT_COLD, 0x454, 0, 100), - SETTING(SOFT_HOT, 0x454, 1, 400), - SETTING(HARD_COLD, 0x454, 2, 50), - SETTING(HARD_HOT, 0x454, 3, 450), +#ifdef CONFIG_MACH_ZUK_Z2_PLUS + SETTING(SOFT_COLD, 0x454, 0, 170), + SETTING(SOFT_HOT, 0x454, 1, 470), + SETTING(HARD_COLD, 0x454, 2, 20), + SETTING(HARD_HOT, 0x454, 3, 520), +#else + SETTING(SOFT_COLD, 0x454, 0, 160), + SETTING(SOFT_HOT, 0x454, 1, 460), + SETTING(HARD_COLD, 0x454, 2, 10), + SETTING(HARD_HOT, 0x454, 3, 510), +#endif SETTING(RESUME_SOC, 0x45C, 1, 0), SETTING(BCL_LM_THRESHOLD, 0x47C, 2, 50), SETTING(BCL_MH_THRESHOLD, 0x47C, 3, 752), SETTING(TERM_CURRENT, 0x40C, 2, 250), SETTING(CHG_TERM_CURRENT, 0x4F8, 2, 250), - SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3100), - SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3200), - SETTING(VBAT_EST_DIFF, 0x000, 0, 30), + SETTING(IRQ_VOLT_EMPTY, 0x458, 3, 3000), + SETTING(CUTOFF_VOLTAGE, 0x40C, 0, 3400), + SETTING(VBAT_EST_DIFF, 0x000, 0, 200), SETTING(DELTA_SOC, 0x450, 3, 1), SETTING(BATT_LOW, 0x458, 0, 4200), SETTING(THERM_DELAY, 0x4AC, 3, 0), @@ -644,6 +651,8 @@ struct fg_chip { bool batt_info_restore; bool *batt_range_ocv; int *batt_range_pct; + ktime_t soc_kt; + u8 is_op_soc; }; /* FG_MEMIF DEBUGFS structures */ @@ -2020,12 +2029,6 @@ static void fg_handle_battery_insertion(struct fg_chip *chip) schedule_delayed_work(&chip->update_sram_data, msecs_to_jiffies(0)); } - -static int soc_to_setpoint(int soc) -{ - return DIV_ROUND_CLOSEST(soc * 255, 100); -} - static void batt_to_setpoint_adc(int vbatt_mv, u8 *data) { int val; @@ -2233,10 +2236,78 @@ static int get_monotonic_soc_raw(struct fg_chip *chip) } #define EMPTY_CAPACITY 0 -#define DEFAULT_CAPACITY 50 +#define DEFAULT_CAPACITY 65 #define MISSING_CAPACITY 100 #define FULL_CAPACITY 100 #define FULL_SOC_RAW 0xFF + +static int bound_soc(int soc) +{ + soc = max(0, soc); + soc = min(100, soc); + return soc; +} + +#define LENUK_OP_FIR_SOC 60 +#define LENUK_OP_SEC_SOC 85 +#define LENUK_SOC_CHANGE_MS 25000 +static int set_soc_remap_point(struct fg_chip *chip, int soc) +{ + int mapped_soc = 0; + if (!chip->is_op_soc) { + chip->soc_kt = ktime_get_boottime(); + mapped_soc = soc; + chip->is_op_soc = 1; + } else { + ktime_t now_kt, delta_kt; + int delta_ms; + now_kt = ktime_get_boottime(); + delta_kt = ktime_sub(now_kt, chip->soc_kt); + delta_ms = (int)div64_s64(ktime_to_ns(delta_kt), 1000000); + if (delta_ms <= LENUK_SOC_CHANGE_MS) { + if (chip->status == POWER_SUPPLY_STATUS_CHARGING) + mapped_soc = soc; + else + mapped_soc = soc + 1; + }else { + if (chip->status == POWER_SUPPLY_STATUS_CHARGING) + mapped_soc = soc + 1; + else + mapped_soc = soc; + } + } + return mapped_soc; +} + +static int soc_remap_process(struct fg_chip *chip, int soc) +{ + int maped_soc = 0; + switch(soc){ + case LENUK_OP_FIR_SOC : + maped_soc = set_soc_remap_point(chip,soc); + break; + case LENUK_OP_SEC_SOC : + maped_soc = set_soc_remap_point(chip,soc) + 1; + break; + default: + chip->is_op_soc = 0; + if(soc >= 61 && soc <= 84 ) + maped_soc = soc + 1; + else if(soc >= 86 && soc <= 100) + maped_soc = bound_soc(soc + 2); + else + maped_soc = soc; + } + pr_info("pre_map_soc is %d,post_map_soc is %d\n",soc,maped_soc); + return maped_soc; +} +static int soc_show_op(struct fg_chip *chip, int msoc) +{ + int soc = DIV_ROUND_CLOSEST((msoc - 1) * (FULL_CAPACITY - 2), + FULL_SOC_RAW - 2) + 1; + return soc_remap_process(chip, soc); +} + static int get_prop_capacity(struct fg_chip *chip) { int msoc, rc; @@ -2284,9 +2355,7 @@ static int get_prop_capacity(struct fg_chip *chip) } else if (msoc == FULL_SOC_RAW) { return FULL_CAPACITY; } - - return DIV_ROUND_CLOSEST((msoc - 1) * (FULL_CAPACITY - 2), - FULL_SOC_RAW - 2) + 1; + return soc_show_op(chip, msoc); } #define HIGH_BIAS 3 @@ -8028,7 +8097,7 @@ static int fg_common_hw_init(struct fg_chip *chip) } rc = fg_mem_masked_write(chip, settings[FG_MEM_DELTA_SOC].address, 0xFF, - soc_to_setpoint(settings[FG_MEM_DELTA_SOC].value), + settings[FG_MEM_DELTA_SOC].value, settings[FG_MEM_DELTA_SOC].offset); if (rc) { pr_err("failed to write delta soc rc=%d\n", rc); diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c index 819c002ae0fc..e61a9c96d681 100644 --- a/drivers/power/supply/qcom/qpnp-smbcharger.c +++ b/drivers/power/supply/qcom/qpnp-smbcharger.c @@ -43,6 +43,13 @@ #include <linux/ktime.h> #include <linux/extcon.h> #include <linux/pmic-voter.h> +#include <linux/cclogic-core.h> + +#define SUPPORT_CCLOGIC_EVENT_TYPE + +#ifdef CONFIG_MACH_ZUK_Z2_PLUS +#define SUPPORT_ONLY_5V_CHARGER +#endif /* Mask/Bit helpers */ #define _SMB_MASK(BITS, POS) \ @@ -293,6 +300,12 @@ struct smbchg_chip { struct votable *hvdcp_enable_votable; /* extcon for VBUS / ID notification to USB */ struct extcon_dev *extcon; + +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + struct notifier_block cclogic_notif; + int cclogic_attached; + wait_queue_head_t cclogic_wait_queue; +#endif }; enum qpnp_schg { @@ -300,6 +313,14 @@ enum qpnp_schg { QPNP_SCHG_LITE, }; +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE +enum cclogic_event { + USB_DETACHED, + USB_ATTACHED, + USB_REMOVE, +}; +#endif + static char *version_str[] = { [QPNP_SCHG] = "SCHG", [QPNP_SCHG_LITE] = "SCHG_LITE", @@ -680,6 +701,14 @@ static enum pwr_path_type smbchg_get_pwr_path(struct smbchg_chip *chip) #define USBIN_SRC_DET_BIT BIT(2) #define FMB_STS_MASK SMB_MASK(3, 0) #define USBID_GND_THRESHOLD 0x495 + +static int id_state = 0; +int get_usb_id_state(void) +{ + return id_state; +} +EXPORT_SYMBOL(get_usb_id_state); + static bool is_otg_present_schg(struct smbchg_chip *chip) { int rc; @@ -761,7 +790,7 @@ static bool is_otg_present(struct smbchg_chip *chip) if (chip->schg_version == QPNP_SCHG_LITE) return is_otg_present_schg_lite(chip); - return is_otg_present_schg(chip); + return is_otg_present_schg(chip) || cclogic_get_otg_state(); } #define USBIN_9V BIT(5) @@ -3859,6 +3888,7 @@ struct regulator_ops smbchg_otg_reg_ops = { #define USBIN_ADAPTER_9V 0x3 #define USBIN_ADAPTER_5V_9V_CONT 0x2 #define USBIN_ADAPTER_5V_UNREGULATED_9V 0x5 +#define USBIN_ADAPTER_5V 0x0 static int smbchg_external_otg_regulator_enable(struct regulator_dev *rdev) { int rc = 0; @@ -3888,9 +3918,15 @@ static int smbchg_external_otg_regulator_enable(struct regulator_dev *rdev) return rc; } +#ifdef SUPPORT_ONLY_5V_CHARGER + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + 0xFF, USBIN_ADAPTER_5V); +#else rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USBIN_CHGR_CFG, 0xFF, USBIN_ADAPTER_9V); +#endif if (rc < 0) { dev_err(chip->dev, "Couldn't write usb allowance rc=%d\n", rc); return rc; @@ -4653,10 +4689,19 @@ static void restore_from_hvdcp_detection(struct smbchg_chip *chip) if (rc < 0) pr_err("Couldn't configure HVDCP 9V rc=%d\n", rc); +#ifdef SUPPORT_ONLY_5V_CHARGER + /* disable HVDCP */ + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_EN_BIT, 0); + if (rc < 0) + pr_err("Couldn't disable HVDCP rc=%d\n", rc); +#else /* enable HVDCP */ rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1); if (rc < 0) pr_err("Couldn't enable HVDCP rc=%d\n", rc); +#endif /* enable APSD */ rc = smbchg_sec_masked_write(chip, @@ -4666,9 +4711,15 @@ static void restore_from_hvdcp_detection(struct smbchg_chip *chip) pr_err("Couldn't enable APSD rc=%d\n", rc); /* Reset back to 5V unregulated */ +#ifdef SUPPORT_ONLY_5V_CHARGER + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + ADAPTER_ALLOWANCE_MASK, USBIN_ADAPTER_5V); +#else rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USBIN_CHGR_CFG, ADAPTER_ALLOWANCE_MASK, USBIN_ADAPTER_5V_UNREGULATED_9V); +#endif if (rc < 0) pr_err("Couldn't write usb allowance rc=%d\n", rc); @@ -4736,7 +4787,7 @@ static void handle_usb_removal(struct smbchg_chip *chip) /* cancel/wait for hvdcp pending work if any */ cancel_delayed_work_sync(&chip->hvdcp_det_work); smbchg_relax(chip, PM_DETECT_HVDCP); - smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN); + smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_USB); extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present); smbchg_request_dpdm(chip, false); schedule_work(&chip->usb_set_online_work); @@ -4933,7 +4984,7 @@ close_time: } #define AICL_IRQ_LIMIT_SECONDS 60 -#define AICL_IRQ_LIMIT_COUNT 25 +#define AICL_IRQ_LIMIT_COUNT 35 static void increment_aicl_count(struct smbchg_chip *chip) { bool bad_charger = false; @@ -5119,11 +5170,18 @@ static int fake_insertion_removal(struct smbchg_chip *chip, bool insertion) pr_smb(PR_MISC, "Allow only %s charger\n", insertion ? "5-9V" : "9V only"); +#ifdef SUPPORT_ONLY_5V_CHARGER + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + USBIN_CHGR_CFG, + ADAPTER_ALLOWANCE_MASK, + USBIN_ADAPTER_5V); +#else rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + USBIN_CHGR_CFG, ADAPTER_ALLOWANCE_MASK, insertion ? USBIN_ADAPTER_5V_9V_CONT : USBIN_ADAPTER_9V); +#endif if (rc < 0) { pr_err("Couldn't write usb allowance rc=%d\n", rc); return rc; @@ -5305,6 +5363,17 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) return rc; } +#ifdef SUPPORT_ONLY_5V_CHARGER + /* disable HVDCP */ + pr_smb(PR_MISC, "Disable HVDCP\n"); + rc = smbchg_sec_masked_write(chip, + chip->usb_chgpth_base + CHGPTH_CFG, + HVDCP_EN_BIT, 0); + if (rc < 0) { + pr_err("Couldn't disable HVDCP rc=%d\n", rc); + return rc; + } +#else /* enable HVDCP */ pr_smb(PR_MISC, "Enable HVDCP\n"); rc = vote(chip->hvdcp_enable_votable, HVDCP_PULSING_VOTER, false, 1); @@ -5312,6 +5381,7 @@ static int smbchg_unprepare_for_pulsing(struct smbchg_chip *chip) pr_err("Couldn't enable HVDCP rc=%d\n", rc); return rc; } +#endif /* enable APSD */ pr_smb(PR_MISC, "Enabling APSD\n"); @@ -5967,6 +6037,7 @@ static int smbchg_battery_set_property(struct power_supply *psy, rc = vote(chip->dc_suspend_votable, USER_EN_VOTER, !val->intval, 0); chip->chg_enabled = val->intval; + power_supply_changed(chip->usb_psy); schedule_work(&chip->usb_set_online_work); break; case POWER_SUPPLY_PROP_CAPACITY: @@ -6632,6 +6703,14 @@ static irqreturn_t usbin_uv_handler(int irq, void *_chip) schedule_work(&chip->usb_set_online_work); } +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + /* usb pull out, wakeup wq if wq waiting cclogic attached event */ + if (reg & USBIN_UV_BIT) { + chip->cclogic_attached = USB_REMOVE; + wake_up_interruptible(&chip->cclogic_wait_queue); + } +#endif + smbchg_wipower_check(chip); out: return IRQ_HANDLED; @@ -6651,6 +6730,9 @@ static irqreturn_t src_detect_handler(int irq, void *_chip) bool usb_present = is_usb_present(chip); bool src_detect = is_src_detect_high(chip); int rc; +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + int ret; +#endif pr_smb(PR_STATUS, "%s chip->usb_present = %d usb_present = %d src_detect = %d hvdcp_3_det_ignore_uv=%d\n", @@ -6691,6 +6773,15 @@ static irqreturn_t src_detect_handler(int irq, void *_chip) if (src_detect) { update_usb_status(chip, usb_present, 0); +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + ret = wait_event_interruptible_timeout(chip->cclogic_wait_queue, + (chip->cclogic_attached == USB_ATTACHED) || + (chip->cclogic_attached == USB_REMOVE), + msecs_to_jiffies(2500)); + pr_info("Waiting cclogic state ret = %d\n", ret); + if (ret == 0) + pr_err("Waiting cclogic state timeout\n"); +#endif } else { update_usb_status(chip, 0, false); chip->aicl_irq_count = 0; @@ -8230,6 +8321,25 @@ static void rerun_hvdcp_det_if_necessary(struct smbchg_chip *chip) } } +/* + * cclogic callback, notify cclogic event status: detached or attached + */ +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE +static int cclogic_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct smbchg_chip *chip = container_of(self, struct smbchg_chip, cclogic_notif); + if (event == 1) { /* usb detached */ + chip->cclogic_attached = USB_DETACHED; + } else if (event == 2) { /* usb attached */ + chip->cclogic_attached = USB_ATTACHED; + wake_up_interruptible(&chip->cclogic_wait_queue); + } + pr_smb(PR_MISC, "setting cclogic_attached = %d\n", + chip->cclogic_attached); + return 0; +} +#endif + static int smbchg_probe(struct platform_device *pdev) { int rc; @@ -8446,6 +8556,10 @@ static int smbchg_probe(struct platform_device *pdev) goto votables_cleanup; } +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + init_waitqueue_head(&chip->cclogic_wait_queue); +#endif + chip->extcon = devm_extcon_dev_allocate(chip->dev, smbchg_extcon_cable); if (IS_ERR(chip->extcon)) { dev_err(chip->dev, "failed to allocate extcon device\n"); @@ -8543,6 +8657,15 @@ static int smbchg_probe(struct platform_device *pdev) } chip->allow_hvdcp3_detection = true; +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE + chip->cclogic_notif.notifier_call = cclogic_notifier_callback; + rc = cclogic_register_client(&chip->cclogic_notif); + if (rc) { + pr_err("Unable to register cclogic_notifier : %d\n", rc); + goto unregister_dc_psy1; + } +#endif + if (chip->cfg_chg_led_support && chip->schg_version == QPNP_SCHG_LITE) { rc = smbchg_register_chg_led(chip); @@ -8585,6 +8708,10 @@ static int smbchg_probe(struct platform_device *pdev) unregister_led_class: if (chip->cfg_chg_led_support && chip->schg_version == QPNP_SCHG_LITE) led_classdev_unregister(&chip->led_cdev); +#ifdef SUPPORT_CCLOGIC_EVENT_TYPE +unregister_dc_psy1: + cclogic_unregister_client(&chip->cclogic_notif); +#endif out: handle_usb_removal(chip); votables_cleanup: @@ -8617,6 +8744,10 @@ static int smbchg_remove(struct platform_device *pdev) debugfs_remove_recursive(chip->debug_root); +#ifdef SUPPORT_SCREEN_ON_FCC_OP + fb_unregister_client(&chip->fb_notif); +#endif + destroy_votable(chip->aicl_deglitch_short_votable); destroy_votable(chip->hw_aicl_rerun_enable_indirect_votable); destroy_votable(chip->hw_aicl_rerun_disable_votable); |