summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/reset/msm-poweroff.c2
-rw-r--r--drivers/power/supply/qcom/pmic-voter.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-fg.c105
-rw-r--r--drivers/power/supply/qcom/qpnp-smbcharger.c137
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);