summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/power_supply_sysfs.c2
-rw-r--r--drivers/power/qcom-charger/bcl_peripheral.c2
-rw-r--r--drivers/power/qcom-charger/qpnp-smb2.c178
-rw-r--r--drivers/power/qcom-charger/smb-lib.c916
-rw-r--r--drivers/power/qcom-charger/smb-lib.h31
-rw-r--r--drivers/power/qcom-charger/smb-reg.h25
-rw-r--r--drivers/power/qcom-charger/smb138x-charger.c12
7 files changed, 836 insertions, 330 deletions
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 0619b314b7de..ea2694c8c58d 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -249,6 +249,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(flash_current_max),
POWER_SUPPLY_ATTR(update_now),
POWER_SUPPLY_ATTR(esr_count),
+ POWER_SUPPLY_ATTR(buck_freq),
POWER_SUPPLY_ATTR(safety_timer_enabled),
POWER_SUPPLY_ATTR(charge_done),
POWER_SUPPLY_ATTR(flash_active),
@@ -273,6 +274,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(charger_temp),
POWER_SUPPLY_ATTR(charger_temp_max),
POWER_SUPPLY_ATTR(parallel_disable),
+ POWER_SUPPLY_ATTR(parallel_percent),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/qcom-charger/bcl_peripheral.c b/drivers/power/qcom-charger/bcl_peripheral.c
index fc958b160f86..8a7012ac2bef 100644
--- a/drivers/power/qcom-charger/bcl_peripheral.c
+++ b/drivers/power/qcom-charger/bcl_peripheral.c
@@ -459,7 +459,7 @@ static void bcl_lmh_dcvs_enable(void)
desc_arg.arginfo = SCM_ARGS(5, SCM_RO, SCM_VAL, SCM_VAL,
SCM_VAL, SCM_VAL);
- dmac_flush_range(payload, payload + 5 * (sizeof(uint32_t)));
+ dmac_flush_range(payload, (void *)payload + 5 * (sizeof(uint32_t)));
if (scm_call2(SCM_SIP_FNID(SCM_SVC_LMH, LMH_DCVSH),
&desc_arg))
pr_err("Error enabling LMH BCL monitoringfor cluster0\n");
diff --git a/drivers/power/qcom-charger/qpnp-smb2.c b/drivers/power/qcom-charger/qpnp-smb2.c
index 9e5df70541f2..dee554b6e150 100644
--- a/drivers/power/qcom-charger/qpnp-smb2.c
+++ b/drivers/power/qcom-charger/qpnp-smb2.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
+#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/platform_device.h>
@@ -216,12 +217,15 @@ struct smb_dt_props {
u32 step_soc_threshold[STEP_CHARGING_MAX_STEPS - 1];
s32 step_cc_delta[STEP_CHARGING_MAX_STEPS];
struct device_node *revid_dev_node;
+ int float_option;
+ bool hvdcp_disable;
};
struct smb2 {
- struct smb_charger chg;
- struct smb_dt_props dt;
- bool bad_part;
+ struct smb_charger chg;
+ struct dentry *dfs_root;
+ struct smb_dt_props dt;
+ bool bad_part;
};
static int __debug_mask;
@@ -229,11 +233,6 @@ module_param_named(
debug_mask, __debug_mask, int, S_IRUSR | S_IWUSR
);
-static int __pl_master_percent = 50;
-module_param_named(
- pl_master_percent, __pl_master_percent, int, S_IRUSR | S_IWUSR
-);
-
#define MICRO_1P5A 1500000
static int smb2_parse_dt(struct smb2 *chip)
{
@@ -320,6 +319,15 @@ static int smb2_parse_dt(struct smb2 *chip)
}
}
+ of_property_read_u32(node, "qcom,float-option", &chip->dt.float_option);
+ if (chip->dt.float_option < 0 || chip->dt.float_option > 4) {
+ pr_err("qcom,float-option is out of range [0, 4]\n");
+ return -EINVAL;
+ }
+
+ chip->dt.hvdcp_disable = of_property_read_bool(node,
+ "qcom,hvdcp-disable");
+
return 0;
}
@@ -333,6 +341,7 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_PD_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_TYPEC_MODE,
@@ -342,7 +351,6 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_PD_ACTIVE,
POWER_SUPPLY_PROP_INPUT_CURRENT_SETTLED,
POWER_SUPPLY_PROP_INPUT_CURRENT_NOW,
- POWER_SUPPLY_PROP_PARALLEL_DISABLE,
};
static int smb2_usb_get_prop(struct power_supply *psy,
@@ -372,6 +380,9 @@ static int smb2_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = smblib_get_prop_usb_voltage_now(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+ rc = smblib_get_prop_pd_current_max(chg, val);
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_get_prop_usb_current_max(chg, val);
break;
@@ -405,9 +416,11 @@ static int smb2_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_INPUT_CURRENT_NOW:
rc = smblib_get_prop_usb_current_now(chg, val);
break;
- case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
- val->intval = get_client_vote(chg->pl_disable_votable,
- USER_VOTER);
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_get_prop_pd_in_hard_reset(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
+ val->intval = chg->system_suspend_supported;
break;
default:
pr_err("get prop %d is not supported\n", psp);
@@ -436,25 +449,23 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_set_prop_usb_voltage_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
+ rc = smblib_set_prop_pd_current_max(chg, val);
+ break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_prop_usb_current_max(chg, val);
break;
- case POWER_SUPPLY_PROP_TYPE:
- if (chg->pd_active && val->intval == POWER_SUPPLY_TYPE_USB_PD) {
- chg->usb_psy_desc.type = val->intval;
- } else {
- pr_err("set type %d not allowed\n", val->intval);
- rc = -EINVAL;
- }
- break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
rc = smblib_set_prop_typec_power_role(chg, val);
break;
case POWER_SUPPLY_PROP_PD_ACTIVE:
rc = smblib_set_prop_pd_active(chg, val);
break;
- case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
- vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
+ case POWER_SUPPLY_PROP_PD_IN_HARD_RESET:
+ rc = smblib_set_prop_pd_in_hard_reset(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED:
+ chg->system_suspend_supported = val->intval;
break;
default:
pr_err("set prop %d is not supported\n", psp);
@@ -470,7 +481,6 @@ static int smb2_usb_prop_is_writeable(struct power_supply *psy,
{
switch (psp) {
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
- case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
return 1;
default:
break;
@@ -629,6 +639,7 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_STEP_CHARGING_ENABLED,
POWER_SUPPLY_PROP_STEP_CHARGING_STEP,
POWER_SUPPLY_PROP_CHARGE_DONE,
+ POWER_SUPPLY_PROP_PARALLEL_DISABLE,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -689,6 +700,10 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_DONE:
rc = smblib_get_prop_batt_charge_done(chg, val);
break;
+ case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
+ val->intval = get_client_vote(chg->pl_disable_votable,
+ USER_VOTER);
+ break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
@@ -719,6 +734,9 @@ static int smb2_batt_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
rc = smblib_set_prop_batt_capacity(chg, val);
break;
+ case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
+ vote(chg->pl_disable_votable, USER_VOTER, (bool)val->intval, 0);
+ break;
default:
rc = -EINVAL;
}
@@ -733,6 +751,7 @@ static int smb2_batt_prop_is_writeable(struct power_supply *psy,
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
case POWER_SUPPLY_PROP_CAPACITY:
+ case POWER_SUPPLY_PROP_PARALLEL_DISABLE:
return 1;
default:
break;
@@ -1022,6 +1041,14 @@ static int smb2_init_hw(struct smb2 *chip)
DEFAULT_VOTER, true, chip->dt.usb_icl_ua);
vote(chg->dc_icl_votable,
DEFAULT_VOTER, true, chip->dt.dc_icl_ua);
+ vote(chg->hvdcp_disable_votable, DEFAULT_VOTER,
+ chip->dt.hvdcp_disable, 0);
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER,
+ true, 0);
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER,
+ true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ true, 0);
/* Configure charge enable for software control; active high */
rc = smblib_masked_write(chg, CHGR_CFG2_REG,
@@ -1119,6 +1146,35 @@ static int smb2_init_hw(struct smb2 *chip)
return rc;
}
+ /* configure float charger options */
+ switch (chip->dt.float_option) {
+ case 1:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, 0);
+ break;
+ case 2:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, FORCE_FLOAT_SDP_CFG_BIT);
+ break;
+ case 3:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, FLOAT_DIS_CHGING_CFG_BIT);
+ break;
+ case 4:
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_2_CFG_REG,
+ FLOAT_OPTIONS_MASK, SUSPEND_FLOAT_CFG_BIT);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure float charger options rc=%d\n",
+ rc);
+ return rc;
+ }
+
return rc;
}
@@ -1439,9 +1495,74 @@ static int smb2_request_interrupts(struct smb2 *chip)
return rc;
}
-/*********
- * PROBE *
- *********/
+#if defined(CONFIG_DEBUG_FS)
+
+static int force_batt_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->batt_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_batt_psy_update_ops, NULL,
+ force_batt_psy_update_write, "0x%02llx\n");
+
+static int force_usb_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->usb_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_usb_psy_update_ops, NULL,
+ force_usb_psy_update_write, "0x%02llx\n");
+
+static int force_dc_psy_update_write(void *data, u64 val)
+{
+ struct smb_charger *chg = data;
+
+ power_supply_changed(chg->dc_psy);
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(force_dc_psy_update_ops, NULL,
+ force_dc_psy_update_write, "0x%02llx\n");
+
+static void smb2_create_debugfs(struct smb2 *chip)
+{
+ struct dentry *file;
+
+ chip->dfs_root = debugfs_create_dir("charger", NULL);
+ if (IS_ERR_OR_NULL(chip->dfs_root)) {
+ pr_err("Couldn't create charger debugfs rc=%ld\n",
+ (long)chip->dfs_root);
+ return;
+ }
+
+ file = debugfs_create_file("force_batt_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_batt_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_batt_psy_update file rc=%ld\n",
+ (long)file);
+
+ file = debugfs_create_file("force_usb_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_usb_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_usb_psy_update file rc=%ld\n",
+ (long)file);
+
+ file = debugfs_create_file("force_dc_psy_update", S_IRUSR | S_IWUSR,
+ chip->dfs_root, chip, &force_dc_psy_update_ops);
+ if (IS_ERR_OR_NULL(file))
+ pr_err("Couldn't create force_dc_psy_update file rc=%ld\n",
+ (long)file);
+}
+
+#else
+
+static void smb2_create_debugfs(struct smb2 *chip)
+{}
+
+#endif
static int smb2_probe(struct platform_device *pdev)
{
@@ -1459,7 +1580,7 @@ static int smb2_probe(struct platform_device *pdev)
chg->param = v1_params;
chg->debug_mask = &__debug_mask;
chg->mode = PARALLEL_MASTER;
- chg->pl.master_percent = &__pl_master_percent;
+ chg->name = "PMI";
chg->regmap = dev_get_regmap(chg->dev->parent, NULL);
if (!chg->regmap) {
@@ -1528,6 +1649,7 @@ static int smb2_probe(struct platform_device *pdev)
return 0;
}
+ chg->pl.slave_pct = 50;
rc = smb2_init_batt_psy(chip);
if (rc < 0) {
pr_err("Couldn't initialize batt psy rc=%d\n", rc);
@@ -1553,6 +1675,8 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
+ smb2_create_debugfs(chip);
+
pr_info("QPNP SMB2 probed successfully\n");
return rc;
diff --git a/drivers/power/qcom-charger/smb-lib.c b/drivers/power/qcom-charger/smb-lib.c
index 3a32b8f3d50a..bcdfdd459b3d 100644
--- a/drivers/power/qcom-charger/smb-lib.c
+++ b/drivers/power/qcom-charger/smb-lib.c
@@ -22,12 +22,18 @@
#include "storm-watch.h"
#include "pmic-voter.h"
+#define smblib_err(chg, fmt, ...) \
+ pr_err("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__) \
+
#define smblib_dbg(chg, reason, fmt, ...) \
do { \
if (*chg->debug_mask & (reason)) \
- dev_info(chg->dev, fmt, ##__VA_ARGS__); \
+ pr_info("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__); \
else \
- dev_dbg(chg->dev, fmt, ##__VA_ARGS__); \
+ pr_debug("%s: %s: " fmt, chg->name, \
+ __func__, ##__VA_ARGS__); \
} while (0)
static bool is_secure(struct smb_charger *chg, int addr)
@@ -85,21 +91,19 @@ unlock:
return rc;
}
-static int smblib_get_step_charging_adjustment(struct smb_charger *chg,
- int *cc_offset)
+static int smblib_get_step_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
{
- int step_state;
- int rc;
+ int rc, step_state;
u8 stat;
if (!chg->step_chg_enabled) {
- *cc_offset = 0;
+ *cc_delta_ua = 0;
return 0;
}
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -107,57 +111,70 @@ static int smblib_get_step_charging_adjustment(struct smb_charger *chg,
step_state = (stat & STEP_CHARGING_STATUS_MASK) >>
STEP_CHARGING_STATUS_SHIFT;
rc = smblib_get_charge_param(chg, &chg->param.step_cc_delta[step_state],
- cc_offset);
+ cc_delta_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
+ return rc;
+ }
- return rc;
+ return 0;
}
-static void smblib_fcc_split_ua(struct smb_charger *chg, int total_fcc,
- int *master_ua, int *slave_ua)
+static int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
{
- int rc, cc_reduction_ua = 0;
- int step_cc_delta;
- int master_percent = min(max(*chg->pl.master_percent, 0), 100);
- union power_supply_propval pval = {0, };
- int effective_fcc;
+ int rc, cc_minus_ua;
+ u8 stat;
- /*
- * if master_percent is 0, s/w will configure master's fcc to zero and
- * slave's fcc to the max. However since master's fcc is zero it
- * disables its own charging and as a result the slave's charging is
- * disabled via the fault line.
- */
+ rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+ rc);
+ return rc;
+ }
- rc = smblib_get_prop_batt_health(chg, &pval);
- if (rc == 0) {
- if (pval.intval == POWER_SUPPLY_HEALTH_WARM
- || pval.intval == POWER_SUPPLY_HEALTH_COOL) {
- rc = smblib_get_charge_param(chg,
- &chg->param.jeita_cc_comp,
- &cc_reduction_ua);
- if (rc < 0) {
- dev_err(chg->dev, "Could not get jeita comp, rc=%d\n",
- rc);
- cc_reduction_ua = 0;
- }
- }
+ if (!(stat & BAT_TEMP_STATUS_SOFT_LIMIT_MASK)) {
+ *cc_delta_ua = 0;
+ return 0;
}
- rc = smblib_get_step_charging_adjustment(chg, &step_cc_delta);
- if (rc < 0)
- step_cc_delta = 0;
+ rc = smblib_get_charge_param(chg, &chg->param.jeita_cc_comp,
+ &cc_minus_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get jeita cc minus rc=%d\n", rc);
+ return rc;
+ }
- /*
- * During JEITA condition and with step_charging enabled, PMI will
- * pick the lower of the two value: (FCC - JEITA current compensation)
- * or (FCC + step_charging current delta)
- */
+ *cc_delta_ua = -cc_minus_ua;
+ return 0;
+}
+
+static void smblib_split_fcc(struct smb_charger *chg, int total_ua,
+ int *master_ua, int *slave_ua)
+{
+ int rc, jeita_cc_delta_ua, step_cc_delta_ua, effective_total_ua,
+ hw_cc_delta_ua = 0;
+
+ rc = smblib_get_step_cc_delta(chg, &step_cc_delta_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get step cc delta rc=%d\n", rc);
+ step_cc_delta_ua = 0;
+ } else {
+ hw_cc_delta_ua = step_cc_delta_ua;
+ }
+
+ rc = smblib_get_jeita_cc_delta(chg, &jeita_cc_delta_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get jeita cc delta rc=%d\n", rc);
+ jeita_cc_delta_ua = 0;
+ } else if (jeita_cc_delta_ua < 0) {
+ /* HW will take the min between JEITA and step charge */
+ hw_cc_delta_ua = min(hw_cc_delta_ua, jeita_cc_delta_ua);
+ }
- effective_fcc = min(max(0, total_fcc - cc_reduction_ua),
- max(0, total_fcc + step_cc_delta));
- *master_ua = (effective_fcc * master_percent) / 100;
- *slave_ua = (effective_fcc - *master_ua) * chg->pl.taper_percent / 100;
- *master_ua = max(0, *master_ua + total_fcc - effective_fcc);
+ effective_total_ua = max(0, total_ua + hw_cc_delta_ua);
+ *slave_ua = (effective_total_ua * chg->pl.slave_pct) / 100;
+ *slave_ua = (*slave_ua * chg->pl.taper_pct) / 100;
+ *master_ua = max(0, total_ua - *slave_ua);
}
/********************
@@ -172,7 +189,7 @@ int smblib_get_charge_param(struct smb_charger *chg,
rc = smblib_read(chg, param->reg, &val_raw);
if (rc < 0) {
- dev_err(chg->dev, "%s: Couldn't read from 0x%04x rc=%d\n",
+ smblib_err(chg, "%s: Couldn't read from 0x%04x rc=%d\n",
param->name, param->reg, rc);
return rc;
}
@@ -194,7 +211,7 @@ int smblib_get_usb_suspend(struct smb_charger *chg, int *suspend)
rc = smblib_read(chg, USBIN_CMD_IL_REG, &temp);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read USBIN_CMD_IL rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read USBIN_CMD_IL rc=%d\n", rc);
return rc;
}
*suspend = temp & USBIN_SUSPEND_BIT;
@@ -208,47 +225,97 @@ struct apsd_result {
const enum power_supply_type pst;
};
+enum {
+ UNKNOWN,
+ SDP,
+ CDP,
+ DCP,
+ OCP,
+ FLOAT,
+ HVDCP2,
+ HVDCP3,
+ MAX_TYPES
+};
+
static const struct apsd_result const smblib_apsd_results[] = {
- {"UNKNOWN", 0, POWER_SUPPLY_TYPE_UNKNOWN},
- {"SDP", SDP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB},
- {"CDP", CDP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_CDP},
- {"DCP", DCP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"OCP", OCP_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"FLOAT", FLOAT_CHARGER_BIT, POWER_SUPPLY_TYPE_USB_DCP},
- {"HVDCP2", DCP_CHARGER_BIT | QC_2P0_BIT, POWER_SUPPLY_TYPE_USB_HVDCP},
- {"HVDCP3", DCP_CHARGER_BIT | QC_3P0_BIT, POWER_SUPPLY_TYPE_USB_HVDCP_3},
+ [UNKNOWN] = {
+ .name = "UNKNOWN",
+ .bit = 0,
+ .pst = POWER_SUPPLY_TYPE_UNKNOWN
+ },
+ [SDP] = {
+ .name = "SDP",
+ .bit = SDP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB
+ },
+ [CDP] = {
+ .name = "CDP",
+ .bit = CDP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_CDP
+ },
+ [DCP] = {
+ .name = "DCP",
+ .bit = DCP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [OCP] = {
+ .name = "OCP",
+ .bit = OCP_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [FLOAT] = {
+ .name = "FLOAT",
+ .bit = FLOAT_CHARGER_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_DCP
+ },
+ [HVDCP2] = {
+ .name = "HVDCP2",
+ .bit = DCP_CHARGER_BIT | QC_2P0_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_HVDCP
+ },
+ [HVDCP3] = {
+ .name = "HVDCP3",
+ .bit = DCP_CHARGER_BIT | QC_3P0_BIT,
+ .pst = POWER_SUPPLY_TYPE_USB_HVDCP_3,
+ },
};
static const struct apsd_result *smblib_get_apsd_result(struct smb_charger *chg)
{
int rc, i;
- u8 stat;
+ u8 apsd_stat, stat;
+ const struct apsd_result *result = &smblib_apsd_results[UNKNOWN];
- rc = smblib_read(chg, APSD_STATUS_REG, &stat);
+ rc = smblib_read(chg, APSD_STATUS_REG, &apsd_stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_STATUS rc=%d\n", rc);
- return &smblib_apsd_results[0];
+ smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
+ return result;
}
- smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
+ smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", apsd_stat);
- if (!(stat & APSD_DTC_STATUS_DONE_BIT))
- return &smblib_apsd_results[0];
+ if (!(apsd_stat & APSD_DTC_STATUS_DONE_BIT))
+ return result;
rc = smblib_read(chg, APSD_RESULT_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_RESULT_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read APSD_RESULT_STATUS rc=%d\n",
rc);
- return &smblib_apsd_results[0];
+ return result;
}
stat &= APSD_RESULT_STATUS_MASK;
for (i = 0; i < ARRAY_SIZE(smblib_apsd_results); i++) {
if (smblib_apsd_results[i].bit == stat)
- return &smblib_apsd_results[i];
+ result = &smblib_apsd_results[i];
+ }
+
+ if (apsd_stat & QC_CHARGER_BIT) {
+ /* since its a qc_charger, either return HVDCP3 or HVDCP2 */
+ if (result != &smblib_apsd_results[HVDCP3])
+ result = &smblib_apsd_results[HVDCP2];
}
- dev_err(chg->dev, "Couldn't find an APSD result for 0x%02x\n", stat);
- return &smblib_apsd_results[0];
+ return result;
}
@@ -268,7 +335,7 @@ int smblib_set_charge_param(struct smb_charger *chg,
return -EINVAL;
} else {
if (val_u > param->max_u || val_u < param->min_u) {
- dev_err(chg->dev, "%s: %d is out of range [%d, %d]\n",
+ smblib_err(chg, "%s: %d is out of range [%d, %d]\n",
param->name, val_u, param->min_u, param->max_u);
return -EINVAL;
}
@@ -278,7 +345,7 @@ int smblib_set_charge_param(struct smb_charger *chg,
rc = smblib_write(chg, param->reg, val_raw);
if (rc < 0) {
- dev_err(chg->dev, "%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
+ smblib_err(chg, "%s: Couldn't write 0x%02x to 0x%04x rc=%d\n",
param->name, val_raw, param->reg, rc);
return rc;
}
@@ -295,14 +362,14 @@ static int step_charge_soc_update(struct smb_charger *chg, int capacity)
rc = smblib_set_charge_param(chg, &chg->param.step_soc, capacity);
if (rc < 0) {
- dev_err(chg->dev, "Error in updating soc, rc=%d\n", rc);
+ smblib_err(chg, "Error in updating soc, rc=%d\n", rc);
return rc;
}
rc = smblib_write(chg, STEP_CHG_SOC_VBATT_V_UPDATE_REG,
STEP_CHG_SOC_VBATT_V_UPDATE_BIT);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't set STEP_CHG_SOC_VBATT_V_UPDATE_REG rc=%d\n",
rc);
return rc;
@@ -318,7 +385,7 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend)
rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
suspend ? USBIN_SUSPEND_BIT : 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
+ smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
@@ -331,7 +398,7 @@ int smblib_set_dc_suspend(struct smb_charger *chg, bool suspend)
rc = smblib_masked_write(chg, DCIN_CMD_IL_REG, DCIN_SUSPEND_BIT,
suspend ? DCIN_SUSPEND_BIT : 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't write %s to DCIN_SUSPEND_BIT rc=%d\n",
+ smblib_err(chg, "Couldn't write %s to DCIN_SUSPEND_BIT rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
@@ -359,14 +426,14 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
} else if (min_allowed_uv < MICRO_12V && max_allowed_uv <= MICRO_12V) {
allowed_voltage = USBIN_ADAPTER_ALLOW_9V_TO_12V;
} else {
- dev_err(chg->dev, "invalid allowed voltage [%d, %d]\n",
+ smblib_err(chg, "invalid allowed voltage [%d, %d]\n",
min_allowed_uv, max_allowed_uv);
return -EINVAL;
}
rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG, allowed_voltage);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't write 0x%02x to USBIN_ADAPTER_ALLOW_CFG rc=%d\n",
+ smblib_err(chg, "Couldn't write 0x%02x to USBIN_ADAPTER_ALLOW_CFG rc=%d\n",
allowed_voltage, rc);
return rc;
}
@@ -378,49 +445,44 @@ static int smblib_set_usb_pd_allowed_voltage(struct smb_charger *chg,
* HELPER FUNCTIONS *
********************/
-static int smblib_update_usb_type(struct smb_charger *chg)
+static int try_rerun_apsd_for_hvdcp(struct smb_charger *chg)
{
- int rc = 0;
const struct apsd_result *apsd_result;
- /* if PD is active, APSD is disabled so won't have a valid result */
- if (chg->pd_active)
- return rc;
-
- apsd_result = smblib_get_apsd_result(chg);
- chg->usb_psy_desc.type = apsd_result->pst;
- return rc;
+ /*
+ * PD_INACTIVE_VOTER on hvdcp_disable_votable indicates whether
+ * apsd rerun was tried earlier
+ */
+ if (get_client_vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER)) {
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER, false, 0);
+ /* ensure hvdcp is enabled */
+ if (!get_effective_result(chg->hvdcp_disable_votable)) {
+ apsd_result = smblib_get_apsd_result(chg);
+ if (apsd_result->pst == POWER_SUPPLY_TYPE_USB_HVDCP) {
+ /* rerun APSD */
+ smblib_dbg(chg, PR_MISC, "rerun APSD\n");
+ smblib_masked_write(chg, CMD_APSD_REG,
+ APSD_RERUN_BIT,
+ APSD_RERUN_BIT);
+ }
+ }
+ }
+ return 0;
}
-static int smblib_detach_usb(struct smb_charger *chg)
+static int smblib_update_usb_type(struct smb_charger *chg)
{
- int rc;
-
- cancel_delayed_work_sync(&chg->hvdcp_detect_work);
- chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_UNKNOWN;
-
- /* 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 set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
- rc);
- return rc;
- }
-
- chg->voltage_min_uv = MICRO_5V;
- chg->voltage_max_uv = MICRO_5V;
+ int rc = 0;
+ const struct apsd_result *apsd_result;
- /* clear USB ICL vote for PD_VOTER */
- rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote for USB ICL rc=%d\n",
- rc);
- return rc;
+ /* if PD is active, APSD is disabled so won't have a valid result */
+ if (chg->pd_active) {
+ chg->usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
+ return 0;
}
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, false, 0);
-
+ apsd_result = smblib_get_apsd_result(chg);
+ chg->usb_psy_desc.type = apsd_result->pst;
return rc;
}
@@ -452,7 +514,7 @@ static int smblib_register_notifier(struct smb_charger *chg)
chg->nb.notifier_call = smblib_notifier_call;
rc = power_supply_reg_notifier(&chg->nb);
if (rc < 0) {
- pr_err("Couldn't register psy notifier rc = %d\n", rc);
+ smblib_err(chg, "Couldn't register psy notifier rc = %d\n", rc);
return rc;
}
@@ -526,41 +588,39 @@ static int smblib_fcc_max_vote_callback(struct votable *votable, void *data,
}
static int smblib_fcc_vote_callback(struct votable *votable, void *data,
- int fcc_ua, const char *client)
+ int total_fcc_ua, const char *client)
{
struct smb_charger *chg = data;
- int rc = 0;
union power_supply_propval pval = {0, };
- int master_ua = fcc_ua, slave_ua;
+ int rc, master_fcc_ua = total_fcc_ua, slave_fcc_ua;
- if (fcc_ua < 0) {
- smblib_dbg(chg, PR_MISC, "No Voter\n");
+ if (total_fcc_ua < 0)
return 0;
- }
if (chg->mode == PARALLEL_MASTER
&& !get_effective_result_locked(chg->pl_disable_votable)) {
- smblib_fcc_split_ua(chg, fcc_ua, &master_ua, &slave_ua);
+ smblib_split_fcc(chg, total_fcc_ua, &master_fcc_ua,
+ &slave_fcc_ua);
/*
* parallel charger is not disabled, implying that
* chg->pl.psy exists
*/
- pval.intval = slave_ua;
+ pval.intval = slave_fcc_ua;
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Could not set parallel fcc, rc=%d\n",
+ smblib_err(chg, "Could not set parallel fcc, rc=%d\n",
rc);
return rc;
}
- chg->pl.slave_fcc = slave_ua;
+ chg->pl.slave_fcc_ua = slave_fcc_ua;
}
- rc = smblib_set_charge_param(chg, &chg->param.fcc, master_ua);
+ rc = smblib_set_charge_param(chg, &chg->param.fcc, master_fcc_ua);
if (rc < 0) {
- dev_err(chg->dev, "Error in setting fcc, rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set master fcc rc=%d\n", rc);
return rc;
}
@@ -582,8 +642,7 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
rc = smblib_set_charge_param(chg, &chg->param.fv, fv_uv);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't set floating voltage rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set floating voltage rc=%d\n", rc);
return rc;
}
@@ -592,7 +651,7 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_VOLTAGE_MAX, &pval);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't set float on parallel rc=%d\n", rc);
return rc;
}
@@ -601,41 +660,67 @@ static int smblib_fv_vote_callback(struct votable *votable, void *data,
return 0;
}
-#define USBIN_25MA 25000
-#define USBIN_100MA 100000
+#define USBIN_25MA 25000
+#define USBIN_100MA 100000
+#define USBIN_150MA 150000
+#define USBIN_500MA 500000
+#define USBIN_900MA 900000
static int smblib_usb_icl_vote_callback(struct votable *votable, void *data,
int icl_ua, const char *client)
{
struct smb_charger *chg = data;
int rc = 0;
- bool suspend;
+ bool suspend = (icl_ua < USBIN_25MA);
+ u8 icl_options = 0;
- if (icl_ua < 0) {
- smblib_dbg(chg, PR_MISC, "No Voter hence suspending\n");
- icl_ua = 0;
- }
-
- suspend = (icl_ua < USBIN_25MA);
if (suspend)
- goto suspend;
+ goto out;
- if (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)
- rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
- USB51_MODE_BIT,
- (icl_ua > USBIN_100MA) ? USB51_MODE_BIT : 0);
- else
+ if (chg->usb_psy_desc.type != POWER_SUPPLY_TYPE_USB) {
rc = smblib_set_charge_param(chg, &chg->param.usb_icl, icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't set HC ICL rc=%d\n", rc);
+ return rc;
+ }
+
+ goto out;
+ }
+
+ /* power source is SDP */
+ switch (icl_ua) {
+ case USBIN_100MA:
+ /* USB 2.0 100mA */
+ icl_options = 0;
+ break;
+ case USBIN_150MA:
+ /* USB 3.0 150mA */
+ icl_options = CFG_USB3P0_SEL_BIT;
+ break;
+ case USBIN_500MA:
+ /* USB 2.0 500mA */
+ icl_options = USB51_MODE_BIT;
+ break;
+ case USBIN_900MA:
+ /* USB 3.0 900mA */
+ icl_options = CFG_USB3P0_SEL_BIT | USB51_MODE_BIT;
+ break;
+ default:
+ smblib_err(chg, "ICL %duA isn't supported for SDP\n", icl_ua);
+ icl_options = 0;
+ break;
+ }
+out:
+ rc = smblib_masked_write(chg, USBIN_ICL_OPTIONS_REG,
+ CFG_USB3P0_SEL_BIT | USB51_MODE_BIT, icl_options);
if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't set USB input current limit rc=%d\n", rc);
+ smblib_err(chg, "Couldn't set ICL opetions rc=%d\n", rc);
return rc;
}
-suspend:
rc = vote(chg->usb_suspend_votable, PD_VOTER, suspend, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s input rc=%d\n",
+ smblib_err(chg, "Couldn't %s input rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
}
@@ -650,8 +735,7 @@ static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua)
rc = smblib_set_charge_param(chg, &chg->param.otg_cl, otg_cl_ua);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set otg current limit rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't set otg current limit rc=%d\n", rc);
return rc;
}
@@ -660,7 +744,7 @@ static int smblib_otg_cl_config(struct smb_charger *chg, int otg_cl_ua)
ENG_SSUPPLY_CFG_SKIP_TH_V0P2_BIT,
otg_cl_ua > MICRO_250MA ? 1 : 0);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't write DC_ENG_SSUPPLY_CFG3_REG rc=%d\n", rc);
return rc;
}
@@ -686,7 +770,7 @@ static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
rc = smblib_set_charge_param(chg, &chg->param.dc_icl, icl_ua);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set DC input current limit rc=%d\n",
+ smblib_err(chg, "Couldn't set DC input current limit rc=%d\n",
rc);
return rc;
}
@@ -694,13 +778,25 @@ static int smblib_dc_icl_vote_callback(struct votable *votable, void *data,
suspend:
rc = vote(chg->dc_suspend_votable, USER_VOTER, suspend, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s DC rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
suspend ? "suspend" : "resume", rc);
return rc;
}
return rc;
}
+static int smblib_pd_disallowed_votable_indirect_callback(
+ struct votable *votable, void *data, int disallowed, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = vote(chg->pd_allowed_votable, PD_DISALLOWED_INDIRECT_VOTER,
+ !disallowed, 0);
+
+ return rc;
+}
+
static int smblib_awake_vote_callback(struct votable *votable, void *data,
int awake, const char *client)
{
@@ -724,7 +820,7 @@ static int smblib_pl_disable_vote_callback(struct votable *votable, void *data,
if (chg->mode != PARALLEL_MASTER || !chg->pl.psy)
return 0;
- chg->pl.taper_percent = 100;
+ chg->pl.taper_pct = 100;
rerun_election(chg->fv_votable);
rerun_election(chg->fcc_votable);
@@ -732,7 +828,7 @@ static int smblib_pl_disable_vote_callback(struct votable *votable, void *data,
rc = power_supply_set_property(chg->pl.psy,
POWER_SUPPLY_PROP_INPUT_SUSPEND, &pval);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't change slave suspend state rc=%d\n", rc);
return rc;
}
@@ -750,7 +846,7 @@ static int smblib_chg_disable_vote_callback(struct votable *votable, void *data,
CHARGING_ENABLE_CMD_BIT,
chg_disable ? 0 : CHARGING_ENABLE_CMD_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s charging rc=%d\n",
+ smblib_err(chg, "Couldn't %s charging rc=%d\n",
chg_disable ? "disable" : "enable", rc);
return rc;
}
@@ -768,6 +864,55 @@ static int smblib_pl_enable_indirect_vote_callback(struct votable *votable,
return 0;
}
+static int smblib_hvdcp_disable_vote_callback(struct votable *votable,
+ void *data,
+ int hvdcp_disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+ u8 val = HVDCP_AUTH_ALG_EN_CFG_BIT
+ | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT | HVDCP_EN_BIT;
+
+ /*
+ * Disable the autonomous bit and auth bit for disabling hvdcp.
+ * This ensures only qc 2.0 detection runs but no vbus
+ * negotiation happens.
+ */
+ if (hvdcp_disable)
+ val = HVDCP_EN_BIT;
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ HVDCP_EN_BIT
+ | HVDCP_AUTONOMOUS_MODE_EN_CFG_BIT
+ | HVDCP_AUTH_ALG_EN_CFG_BIT,
+ val);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't %s hvdcp rc=%d\n",
+ hvdcp_disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+static int smblib_apsd_disable_vote_callback(struct votable *votable,
+ void *data,
+ int apsd_disable, const char *client)
+{
+ struct smb_charger *chg = data;
+ int rc;
+
+ rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
+ AUTO_SRC_DETECT_BIT,
+ apsd_disable ? 0 : AUTO_SRC_DETECT_BIT);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't %s APSD rc=%d\n",
+ apsd_disable ? "disable" : "enable", rc);
+ return rc;
+ }
+
+ return 0;
+}
/*****************
* OTG REGULATOR *
*****************/
@@ -783,21 +928,21 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev)
ENG_BUCKBOOST_HALT1_8_MODE_BIT,
ENG_BUCKBOOST_HALT1_8_MODE_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
+ smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
rc);
return rc;
}
rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't enable OTG regulator rc=%d\n", rc);
+ smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc);
return rc;
}
msleep(OTG_SOFT_START_DELAY_MS);
rc = smblib_read(chg, OTG_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read OTG_STATUS_REG rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read OTG_STATUS_REG rc=%d\n", rc);
return rc;
}
if (stat & BOOST_SOFTSTART_DONE_BIT)
@@ -813,7 +958,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
rc = smblib_write(chg, CMD_OTG_REG, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't disable OTG regulator rc=%d\n", rc);
+ smblib_err(chg, "Couldn't disable OTG regulator rc=%d\n", rc);
return rc;
}
@@ -822,7 +967,7 @@ int smblib_vbus_regulator_disable(struct regulator_dev *rdev)
rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG,
ENG_BUCKBOOST_HALT1_8_MODE_BIT, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
+ smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n",
rc);
return rc;
}
@@ -839,7 +984,7 @@ int smblib_vbus_regulator_is_enabled(struct regulator_dev *rdev)
rc = smblib_read(chg, CMD_OTG_REG, &cmd);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read CMD_OTG rc=%d", rc);
+ smblib_err(chg, "Couldn't read CMD_OTG rc=%d", rc);
return rc;
}
@@ -862,7 +1007,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
*/
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
stat = stat & CC_ORIENTATION_BIT ? 0 : VCONN_EN_ORIENTATION_BIT;
@@ -870,7 +1015,7 @@ int smblib_vconn_regulator_enable(struct regulator_dev *rdev)
VCONN_EN_VALUE_BIT | VCONN_EN_ORIENTATION_BIT,
VCONN_EN_VALUE_BIT | stat);
if (rc < 0)
- dev_err(chg->dev, "Couldn't enable vconn setting rc=%d\n", rc);
+ smblib_err(chg, "Couldn't enable vconn setting rc=%d\n", rc);
return rc;
}
@@ -883,7 +1028,7 @@ int smblib_vconn_regulator_disable(struct regulator_dev *rdev)
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
VCONN_EN_VALUE_BIT, 0);
if (rc < 0)
- dev_err(chg->dev, "Couldn't disable vconn regulator rc=%d\n",
+ smblib_err(chg, "Couldn't disable vconn regulator rc=%d\n",
rc);
return rc;
@@ -897,7 +1042,7 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev)
rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &cmd);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
rc);
return rc;
}
@@ -925,8 +1070,7 @@ int smblib_get_prop_batt_present(struct smb_charger *chg,
rc = smblib_read(chg, BATIF_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATIF_INT_RT_STS rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read BATIF_INT_RT_STS rc=%d\n", rc);
return rc;
}
@@ -962,7 +1106,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_get_prop_usb_online(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get usb online property rc=%d\n",
+ smblib_err(chg, "Couldn't get usb online property rc=%d\n",
rc);
return rc;
}
@@ -970,7 +1114,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_get_prop_dc_online(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get dc online property rc=%d\n",
+ smblib_err(chg, "Couldn't get dc online property rc=%d\n",
rc);
return rc;
}
@@ -983,7 +1127,7 @@ int smblib_get_prop_batt_status(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1020,7 +1164,7 @@ int smblib_get_prop_batt_charge_type(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1052,7 +1196,7 @@ int smblib_get_prop_batt_health(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_2_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_2 rc=%d\n",
rc);
return rc;
}
@@ -1060,7 +1204,7 @@ int smblib_get_prop_batt_health(struct smb_charger *chg,
stat);
if (stat & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
- dev_err(chg->dev, "battery over-voltage\n");
+ smblib_err(chg, "battery over-voltage\n");
val->intval = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
goto done;
}
@@ -1095,7 +1239,7 @@ int smblib_get_prop_input_current_limited(struct smb_charger *chg,
rc = smblib_read(chg, AICL_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read AICL_STATUS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n", rc);
return rc;
}
val->intval = (stat & SOFT_ILIMIT_BIT) || chg->is_hdc;
@@ -1154,7 +1298,7 @@ int smblib_get_prop_step_chg_step(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1173,7 +1317,7 @@ int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return rc;
}
@@ -1194,14 +1338,14 @@ int smblib_set_prop_input_suspend(struct smb_charger *chg,
rc = vote(chg->usb_suspend_votable, USER_VOTER, (bool)val->intval, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s USB rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s USB rc=%d\n",
(bool)val->intval ? "suspend" : "resume", rc);
return rc;
}
rc = vote(chg->dc_suspend_votable, USER_VOTER, (bool)val->intval, 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't vote to %s DC rc=%d\n",
+ smblib_err(chg, "Couldn't vote to %s DC rc=%d\n",
(bool)val->intval ? "suspend" : "resume", rc);
return rc;
}
@@ -1258,7 +1402,7 @@ int smblib_get_prop_dc_present(struct smb_charger *chg,
rc = smblib_read(chg, DC_INT_RT_STS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read DC_INT_RT_STS_REG rc=%d\n",
+ smblib_err(chg, "Couldn't read DC_INT_RT_STS_REG rc=%d\n",
rc);
return rc;
}
@@ -1283,7 +1427,7 @@ int smblib_get_prop_dc_online(struct smb_charger *chg,
rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
rc);
return rc;
}
@@ -1328,8 +1472,7 @@ int smblib_get_prop_usb_present(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
@@ -1353,7 +1496,7 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
rc = smblib_read(chg, POWER_PATH_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read POWER_PATH_STATUS rc=%d\n",
+ smblib_err(chg, "Couldn't read POWER_PATH_STATUS rc=%d\n",
rc);
return rc;
}
@@ -1384,10 +1527,18 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval);
}
+int smblib_get_prop_pd_current_max(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
+ return 0;
+}
+
int smblib_get_prop_usb_current_max(struct smb_charger *chg,
union power_supply_propval *val)
{
- val->intval = get_effective_result_locked(chg->usb_icl_votable);
+ val->intval = get_client_vote_locked(chg->usb_icl_votable,
+ USB_PSY_VOTER);
return 0;
}
@@ -1452,8 +1603,7 @@ int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return rc;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n",
@@ -1487,7 +1637,7 @@ static int smblib_get_prop_ufp_mode(struct smb_charger *chg)
rc = smblib_read(chg, TYPE_C_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_1 rc=%d\n", rc);
return POWER_SUPPLY_TYPEC_NONE;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_1 = 0x%02x\n", stat);
@@ -1515,7 +1665,7 @@ static int smblib_get_prop_dfp_mode(struct smb_charger *chg)
rc = smblib_read(chg, TYPE_C_STATUS_2_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_2 rc=%d\n", rc);
return POWER_SUPPLY_TYPEC_NONE;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_2 = 0x%02x\n", stat);
@@ -1546,7 +1696,7 @@ int smblib_get_prop_typec_mode(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
val->intval = POWER_SUPPLY_TYPEC_NONE;
return rc;
}
@@ -1573,7 +1723,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
rc);
return rc;
}
@@ -1597,7 +1747,7 @@ int smblib_get_prop_typec_power_role(struct smb_charger *chg,
break;
default:
val->intval = POWER_SUPPLY_TYPEC_PR_NONE;
- dev_err(chg->dev, "unsupported power role 0x%02lx\n",
+ smblib_err(chg, "unsupported power role 0x%02lx\n",
ctrl & (DFP_EN_CMD_BIT | UFP_EN_CMD_BIT));
return -EINVAL;
}
@@ -1618,16 +1768,55 @@ int smblib_get_prop_input_current_settled(struct smb_charger *chg,
return smblib_get_charge_param(chg, &chg->param.icl_stat, &val->intval);
}
+int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc;
+ u8 ctrl;
+
+ rc = smblib_read(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, &ctrl);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG rc=%d\n",
+ rc);
+ return rc;
+ }
+ val->intval = ctrl & EXIT_SNK_BASED_ON_CC_BIT;
+ return 0;
+}
+
/*******************
* USB PSY SETTERS *
* *****************/
+int smblib_set_prop_pd_current_max(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc;
+
+ if (chg->pd_active)
+ rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
+ else
+ rc = -EPERM;
+
+ return rc;
+}
+
int smblib_set_prop_usb_current_max(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc;
- rc = vote(chg->usb_icl_votable, PD_VOTER, true, val->intval);
+ if (!chg->pd_active) {
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ true, val->intval);
+ } else if (chg->system_suspend_supported) {
+ if (val->intval <= USBIN_25MA)
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ true, val->intval);
+ else
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER,
+ false, 0);
+ }
return rc;
}
@@ -1651,14 +1840,14 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
power_role = DFP_EN_CMD_BIT;
break;
default:
- dev_err(chg->dev, "power role %d not supported\n", val->intval);
+ smblib_err(chg, "power role %d not supported\n", val->intval);
return -EINVAL;
}
rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
TYPEC_POWER_ROLE_CMD_MASK, power_role);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
+ smblib_err(chg, "Couldn't write 0x%02x to TYPE_C_INTRPT_ENB_SOFTWARE_CTRL rc=%d\n",
power_role, rc);
return rc;
}
@@ -1675,7 +1864,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
rc = smblib_set_usb_pd_allowed_voltage(chg, min_uv,
chg->voltage_max_uv);
if (rc < 0) {
- dev_err(chg->dev, "invalid max voltage %duV rc=%d\n",
+ smblib_err(chg, "invalid max voltage %duV rc=%d\n",
val->intval, rc);
return rc;
}
@@ -1697,7 +1886,7 @@ int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
rc = smblib_set_usb_pd_allowed_voltage(chg, chg->voltage_min_uv,
max_uv);
if (rc < 0) {
- dev_err(chg->dev, "invalid min voltage %duV rc=%d\n",
+ smblib_err(chg, "invalid min voltage %duV rc=%d\n",
val->intval, rc);
return rc;
}
@@ -1710,60 +1899,75 @@ int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc;
- u8 stat;
+ u8 stat = 0;
+ bool cc_debounced;
+ bool orientation;
+ bool pd_active = val->intval;
if (!get_effective_result(chg->pd_allowed_votable)) {
- dev_err(chg->dev, "PD is not allowed\n");
+ smblib_err(chg, "PD is not allowed\n");
return -EINVAL;
}
- rc = smblib_masked_write(chg, USBIN_OPTIONS_1_CFG_REG,
- AUTO_SRC_DETECT_BIT,
- val->intval ? 0 : AUTO_SRC_DETECT_BIT);
- if (rc < 0) {
- dev_err(chg->dev, "Couldn't %s APSD rc=%d\n",
- val->intval ? "disable" : "enable", rc);
- return rc;
- }
-
- vote(chg->pd_allowed_votable, PD_VOTER, val->intval, 0);
+ vote(chg->apsd_disable_votable, PD_VOTER, pd_active, 0);
+ vote(chg->pd_allowed_votable, PD_VOTER, pd_active, 0);
/*
* VCONN_EN_ORIENTATION_BIT controls whether to use CC1 or CC2 line
* when TYPEC_SPARE_CFG_BIT (CC pin selection s/w override) is set
* or when VCONN_EN_VALUE_BIT is set.
*/
- if (val->intval) {
- rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
- if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
- return rc;
- }
+ rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
+ return rc;
+ }
- stat &= CC_ORIENTATION_BIT;
+ if (pd_active) {
+ orientation = stat & CC_ORIENTATION_BIT;
rc = smblib_masked_write(chg,
- TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- VCONN_EN_ORIENTATION_BIT,
- stat ? 0 : VCONN_EN_ORIENTATION_BIT);
- if (rc < 0)
- dev_err(chg->dev,
+ TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ VCONN_EN_ORIENTATION_BIT,
+ orientation ? 0 : VCONN_EN_ORIENTATION_BIT);
+ if (rc < 0) {
+ smblib_err(chg,
"Couldn't enable vconn on CC line rc=%d\n", rc);
+ return rc;
+ }
}
/* CC pin selection s/w override in PD session; h/w otherwise. */
rc = smblib_masked_write(chg, TAPER_TIMER_SEL_CFG_REG,
TYPEC_SPARE_CFG_BIT,
- val->intval ? TYPEC_SPARE_CFG_BIT : 0);
+ pd_active ? TYPEC_SPARE_CFG_BIT : 0);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't change cc_out ctrl to %s rc=%d\n",
- val->intval ? "SW" : "HW", rc);
+ smblib_err(chg, "Couldn't change cc_out ctrl to %s rc=%d\n",
+ pd_active ? "SW" : "HW", rc);
return rc;
}
- chg->pd_active = (bool)val->intval;
+ cc_debounced = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+ if (!pd_active && cc_debounced)
+ try_rerun_apsd_for_hvdcp(chg);
+
+ chg->pd_active = pd_active;
smblib_update_usb_type(chg);
+ power_supply_changed(chg->usb_psy);
+
+ return rc;
+}
+
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val)
+{
+ int rc;
+
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ EXIT_SNK_BASED_ON_CC_BIT,
+ (val->intval) ? EXIT_SNK_BASED_ON_CC_BIT : 0);
+
+ vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, val->intval, 0);
+
return rc;
}
@@ -1836,7 +2040,7 @@ irqreturn_t smblib_handle_chg_state_change(int irq, void *data)
rc = smblib_read(chg, BATTERY_CHARGER_STATUS_1_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
+ smblib_err(chg, "Couldn't read BATTERY_CHARGER_STATUS_1 rc=%d\n",
rc);
return IRQ_HANDLED;
}
@@ -1891,7 +2095,7 @@ irqreturn_t smblib_handle_step_chg_soc_update_request(int irq, void *data)
rc = smblib_get_prop_batt_capacity(chg, &pval);
if (rc < 0)
- dev_err(chg->dev, "Couldn't get batt capacity rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
else
step_charge_soc_update(chg, pval.intval);
@@ -1940,7 +2144,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
"dpdm-supply", NULL)) {
chg->dpdm_reg = devm_regulator_get(chg->dev, "dpdm");
if (IS_ERR(chg->dpdm_reg)) {
- dev_err(chg->dev, "Couldn't get dpdm regulator rc=%ld\n",
+ smblib_err(chg, "Couldn't get dpdm regulator rc=%ld\n",
PTR_ERR(chg->dpdm_reg));
chg->dpdm_reg = NULL;
}
@@ -1951,7 +2155,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
return IRQ_HANDLED;
}
@@ -1962,7 +2166,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
smblib_dbg(chg, PR_MISC, "enabling DPDM regulator\n");
rc = regulator_enable(chg->dpdm_reg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't enable dpdm regulator rc=%d\n",
+ smblib_err(chg, "Couldn't enable dpdm regulator rc=%d\n",
rc);
}
} else {
@@ -1970,7 +2174,7 @@ irqreturn_t smblib_handle_usb_plugin(int irq, void *data)
smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
rc = regulator_disable(chg->dpdm_reg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't disable dpdm regulator rc=%d\n",
+ smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
rc);
}
}
@@ -1982,23 +2186,23 @@ skip_dpdm_float:
return IRQ_HANDLED;
}
-#define USB_WEAK_INPUT_MA 1400000
+#define USB_WEAK_INPUT_UA 1400000
irqreturn_t smblib_handle_icl_change(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
- int icl_ma;
- int rc;
+ int rc, icl_ua;
- rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ma);
+
+ rc = smblib_get_charge_param(chg, &chg->param.icl_stat, &icl_ua);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get ICL status rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get ICL status rc=%d\n", rc);
return IRQ_HANDLED;
}
if (chg->mode == PARALLEL_MASTER)
vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER,
- icl_ma >= USB_WEAK_INPUT_MA, 0);
+ icl_ua >= USB_WEAK_INPUT_UA, 0);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: %s\n", irq_data->name);
@@ -2047,9 +2251,13 @@ static void smblib_handle_hvdcp_3p0_auth_done(struct smb_charger *chg,
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
bool rising, bool qc_charger)
{
- if (rising && !qc_charger) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
- power_supply_changed(chg->usb_psy);
+ /* Hold off PD only until hvdcp 2.0 detection timeout */
+ if (rising) {
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+ if (get_effective_result(chg->pd_disallowed_votable_indirect))
+ /* could be a legacy cable, try doing hvdcp */
+ try_rerun_apsd_for_hvdcp(chg);
}
smblib_dbg(chg, PR_INTERRUPT, "IRQ: smblib_handle_hvdcp_check_timeout %s\n",
@@ -2084,7 +2292,9 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
case CDP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ /* if not DCP then no hvdcp timeout happens. Enable pd here */
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
break;
case DCP_CHARGER_BIT:
if (chg->wa_flags & QC_CHARGER_DETECTION_WA_BIT)
@@ -2097,7 +2307,7 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
rc = smblib_update_usb_type(chg);
if (rc < 0)
- dev_err(chg->dev, "Couldn't update usb type rc=%d\n", rc);
+ smblib_err(chg, "Couldn't update usb type rc=%d\n", rc);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: apsd-done rising; %s detected\n",
apsd_result->name);
@@ -2112,7 +2322,7 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
rc = smblib_read(chg, APSD_STATUS_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read APSD_STATUS rc=%d\n", rc);
+ smblib_err(chg, "Couldn't read APSD_STATUS rc=%d\n", rc);
return IRQ_HANDLED;
}
smblib_dbg(chg, PR_REGISTER, "APSD_STATUS = 0x%02x\n", stat);
@@ -2144,48 +2354,124 @@ irqreturn_t smblib_handle_usb_source_change(int irq, void *data)
return IRQ_HANDLED;
}
-static void smblib_handle_typec_cc(struct smb_charger *chg, bool attached)
+static void typec_source_removal(struct smb_charger *chg)
{
int rc;
- if (!attached) {
- rc = smblib_detach_usb(chg);
- if (rc < 0)
- dev_err(chg->dev, "Couldn't detach USB rc=%d\n", rc);
+ vote(chg->pl_disable_votable, TYPEC_SRC_VOTER, true, 0);
+ /* reset both usbin current and voltage votes */
+ vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
+ vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
+ /* reset taper_end voter here */
+ vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
+
+ cancel_delayed_work_sync(&chg->hvdcp_detect_work);
+
+ /* 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)
+ smblib_err(chg, "Couldn't set USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V rc=%d\n",
+ rc);
+
+ chg->voltage_min_uv = MICRO_5V;
+ chg->voltage_max_uv = MICRO_5V;
+
+ /* clear USB ICL vote for PD_VOTER */
+ rc = vote(chg->usb_icl_votable, PD_VOTER, false, 0);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+
+ /* clear USB ICL vote for USB_PSY_VOTER */
+ rc = vote(chg->usb_icl_votable, USB_PSY_VOTER, false, 0);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't un-vote for USB ICL rc=%d\n", rc);
+}
+
+static void typec_source_insertion(struct smb_charger *chg)
+{
+ vote(chg->pl_disable_votable, TYPEC_SRC_VOTER, false, 0);
+}
+
+static void typec_sink_insertion(struct smb_charger *chg)
+{
+ /* when a sink is inserted we should not wait on hvdcp timeout to
+ * enable pd
+ */
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+}
+
+static void smblib_handle_typec_removal(struct smb_charger *chg)
+{
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
+
+ /* reset votes from vbus_cc_short */
+ vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, true, 0);
+
+ vote(chg->hvdcp_disable_votable, PD_INACTIVE_VOTER, true, 0);
+
+ /*
+ * cable could be removed during hard reset, remove its vote to
+ * disable apsd
+ */
+ vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
+
+ typec_source_removal(chg);
+
+ smblib_update_usb_type(chg);
+}
+
+static void smblib_handle_typec_insertion(struct smb_charger *chg,
+ bool sink_attached, bool legacy_cable)
+{
+ int rp;
+ bool vbus_cc_short = false;
+
+ vote(chg->pd_disallowed_votable_indirect, CC_DETACHED_VOTER, false, 0);
+
+ if (sink_attached) {
+ typec_source_removal(chg);
+ typec_sink_insertion(chg);
+ } else {
+ typec_source_insertion(chg);
}
- smblib_dbg(chg, PR_INTERRUPT, "IRQ: CC %s\n",
- attached ? "attached" : "detached");
+ vote(chg->pd_disallowed_votable_indirect, LEGACY_CABLE_VOTER,
+ legacy_cable, 0);
+
+ if (legacy_cable) {
+ rp = smblib_get_prop_ufp_mode(chg);
+ if (rp == POWER_SUPPLY_TYPEC_SOURCE_HIGH
+ || rp == POWER_SUPPLY_TYPEC_NON_COMPLIANT) {
+ vbus_cc_short = true;
+ smblib_err(chg, "Disabling PD and HVDCP, VBUS-CC shorted, rp = %d found\n",
+ rp);
+ }
+ }
+
+ vote(chg->hvdcp_disable_votable, VBUS_CC_SHORT_VOTER, vbus_cc_short, 0);
+ vote(chg->pd_disallowed_votable_indirect, VBUS_CC_SHORT_VOTER,
+ vbus_cc_short, 0);
}
static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
- bool rising, bool sink_attached)
+ bool rising, bool sink_attached, bool legacy_cable)
{
int rc;
union power_supply_propval pval = {0, };
- /* allow PD for attached sinks */
- if (rising && sink_attached)
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ if (rising)
+ smblib_handle_typec_insertion(chg, sink_attached, legacy_cable);
+ else
+ smblib_handle_typec_removal(chg);
rc = smblib_get_prop_typec_mode(chg, &pval);
if (rc < 0)
- dev_err(chg->dev, "Couldn't get prop typec mode rc=%d\n", rc);
-
- /*
- * vote to enable parallel charging if a source is attached, and disable
- * otherwise
- */
- vote(chg->pl_disable_votable, TYPEC_SRC_VOTER,
- !rising || sink_attached, 0);
-
- if (!rising || sink_attached) {
- /* reset both usbin current and voltage votes */
- vote(chg->pl_enable_votable_indirect, USBIN_I_VOTER, false, 0);
- vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0);
- /* reset taper_end voter here */
- vote(chg->pl_disable_votable, TAPER_END_VOTER, false, 0);
- }
+ smblib_err(chg, "Couldn't get prop typec mode rc=%d\n", rc);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: debounce-done %s; Type-C %s detected\n",
rising ? "rising" : "falling",
@@ -2198,20 +2484,27 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
struct smb_charger *chg = irq_data->parent_data;
int rc;
u8 stat;
+ bool debounce_done, sink_attached, legacy_cable;
rc = smblib_read(chg, TYPE_C_STATUS_4_REG, &stat);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't read TYPE_C_STATUS_4 rc=%d\n",
- rc);
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_4 rc=%d\n", rc);
return IRQ_HANDLED;
}
smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_4 = 0x%02x\n", stat);
+ debounce_done = (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT);
+ sink_attached = (bool)(stat & UFP_DFP_MODE_STATUS_BIT);
+
+ rc = smblib_read(chg, TYPE_C_STATUS_5_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_5 rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_5 = 0x%02x\n", stat);
+ legacy_cable = (bool)(stat & TYPEC_LEGACY_CABLE_STATUS_BIT);
- smblib_handle_typec_cc(chg,
- (bool)(stat & CC_ATTACHED_BIT));
smblib_handle_typec_debounce_done(chg,
- (bool)(stat & TYPEC_DEBOUNCE_DONE_STATUS_BIT),
- (bool)(stat & UFP_DFP_MODE_STATUS_BIT));
+ debounce_done, sink_attached, legacy_cable);
power_supply_changed(chg->usb_psy);
@@ -2250,14 +2543,15 @@ static void smblib_hvdcp_detect_work(struct work_struct *work)
{
struct smb_charger *chg = container_of(work, struct smb_charger,
hvdcp_detect_work.work);
- const struct apsd_result *apsd_result;
- apsd_result = smblib_get_apsd_result(chg);
- if (apsd_result->bit &&
- !(apsd_result->bit & (QC_2P0_BIT | QC_3P0_BIT))) {
- vote(chg->pd_allowed_votable, DEFAULT_VOTER, true, 0);
+ vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
+ false, 0);
+ if (get_effective_result(chg->pd_disallowed_votable_indirect))
+ /* pd is still disabled, try hvdcp */
+ try_rerun_apsd_for_hvdcp(chg);
+ else
+ /* notify pd now that pd is allowed */
power_supply_changed(chg->usb_psy);
- }
}
static void bms_update_work(struct work_struct *work)
@@ -2276,7 +2570,7 @@ static void step_soc_req_work(struct work_struct *work)
rc = smblib_get_prop_batt_capacity(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get batt capacity rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt capacity rc=%d\n", rc);
return;
}
@@ -2293,7 +2587,7 @@ static void smblib_pl_detect_work(struct work_struct *work)
#define MINIMUM_PARALLEL_FCC_UA 500000
#define PL_TAPER_WORK_DELAY_MS 100
-#define TAPER_RESIDUAL_PERCENT 75
+#define TAPER_RESIDUAL_PCT 75
static void smblib_pl_taper_work(struct work_struct *work)
{
struct smb_charger *chg = container_of(work, struct smb_charger,
@@ -2301,22 +2595,22 @@ static void smblib_pl_taper_work(struct work_struct *work)
union power_supply_propval pval = {0, };
int rc;
- if (chg->pl.slave_fcc < MINIMUM_PARALLEL_FCC_UA) {
+ if (chg->pl.slave_fcc_ua < MINIMUM_PARALLEL_FCC_UA) {
vote(chg->pl_disable_votable, TAPER_END_VOTER, true, 0);
goto done;
}
rc = smblib_get_prop_batt_charge_type(chg, &pval);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't get batt charge type rc=%d\n", rc);
+ smblib_err(chg, "Couldn't get batt charge type rc=%d\n", rc);
goto done;
}
if (pval.intval == POWER_SUPPLY_CHARGE_TYPE_TAPER) {
vote(chg->awake_votable, PL_TAPER_WORK_RUNNING_VOTER, true, 0);
/* Reduce the taper percent by 25 percent */
- chg->pl.taper_percent = chg->pl.taper_percent
- * TAPER_RESIDUAL_PERCENT / 100;
+ chg->pl.taper_pct = chg->pl.taper_pct
+ * TAPER_RESIDUAL_PCT / 100;
rerun_election(chg->fcc_votable);
schedule_delayed_work(&chg->pl_taper_work,
msecs_to_jiffies(PL_TAPER_WORK_DELAY_MS));
@@ -2398,8 +2692,16 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
- chg->pd_allowed_votable = create_votable("PD_ALLOWED", VOTE_SET_ANY,
- NULL, NULL);
+ chg->pd_disallowed_votable_indirect
+ = create_votable("PD_DISALLOWED_INDIRECT", VOTE_SET_ANY,
+ smblib_pd_disallowed_votable_indirect_callback, chg);
+ if (IS_ERR(chg->pd_disallowed_votable_indirect)) {
+ rc = PTR_ERR(chg->pd_disallowed_votable_indirect);
+ return rc;
+ }
+
+ chg->pd_allowed_votable = create_votable("PD_ALLOWED",
+ VOTE_SET_ANY, NULL, NULL);
if (IS_ERR(chg->pd_allowed_votable)) {
rc = PTR_ERR(chg->pd_allowed_votable);
return rc;
@@ -2438,6 +2740,24 @@ static int smblib_create_votables(struct smb_charger *chg)
return rc;
}
+ chg->hvdcp_disable_votable = create_votable("HVDCP_DISABLE",
+ VOTE_SET_ANY,
+ smblib_hvdcp_disable_vote_callback,
+ chg);
+ if (IS_ERR(chg->hvdcp_disable_votable)) {
+ rc = PTR_ERR(chg->hvdcp_disable_votable);
+ return rc;
+ }
+
+ chg->apsd_disable_votable = create_votable("APSD_DISABLE",
+ VOTE_SET_ANY,
+ smblib_apsd_disable_vote_callback,
+ chg);
+ if (IS_ERR(chg->apsd_disable_votable)) {
+ rc = PTR_ERR(chg->apsd_disable_votable);
+ return rc;
+ }
+
return rc;
}
@@ -2457,6 +2777,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->usb_icl_votable);
if (chg->dc_icl_votable)
destroy_votable(chg->dc_icl_votable);
+ if (chg->pd_disallowed_votable_indirect)
+ destroy_votable(chg->pd_disallowed_votable_indirect);
if (chg->pd_allowed_votable)
destroy_votable(chg->pd_allowed_votable);
if (chg->awake_votable)
@@ -2467,6 +2789,8 @@ static void smblib_destroy_votables(struct smb_charger *chg)
destroy_votable(chg->chg_disable_votable);
if (chg->pl_enable_votable_indirect)
destroy_votable(chg->pl_enable_votable_indirect);
+ if (chg->apsd_disable_votable)
+ destroy_votable(chg->apsd_disable_votable);
}
static void smblib_iio_deinit(struct smb_charger *chg)
@@ -2500,14 +2824,14 @@ int smblib_init(struct smb_charger *chg)
case PARALLEL_MASTER:
rc = smblib_create_votables(chg);
if (rc < 0) {
- dev_err(chg->dev, "Couldn't create votables rc=%d\n",
+ smblib_err(chg, "Couldn't create votables rc=%d\n",
rc);
return rc;
}
rc = smblib_register_notifier(chg);
if (rc < 0) {
- dev_err(chg->dev,
+ smblib_err(chg,
"Couldn't register notifier rc=%d\n", rc);
return rc;
}
@@ -2522,7 +2846,7 @@ int smblib_init(struct smb_charger *chg)
case PARALLEL_SLAVE:
break;
default:
- dev_err(chg->dev, "Unsupported mode %d\n", chg->mode);
+ smblib_err(chg, "Unsupported mode %d\n", chg->mode);
return -EINVAL;
}
@@ -2539,7 +2863,7 @@ int smblib_deinit(struct smb_charger *chg)
case PARALLEL_SLAVE:
break;
default:
- dev_err(chg->dev, "Unsupported mode %d\n", chg->mode);
+ smblib_err(chg, "Unsupported mode %d\n", chg->mode);
return -EINVAL;
}
diff --git a/drivers/power/qcom-charger/smb-lib.h b/drivers/power/qcom-charger/smb-lib.h
index b57114774f8f..9612b740d84f 100644
--- a/drivers/power/qcom-charger/smb-lib.h
+++ b/drivers/power/qcom-charger/smb-lib.h
@@ -27,6 +27,7 @@ enum print_reason {
#define DEFAULT_VOTER "DEFAULT_VOTER"
#define USER_VOTER "USER_VOTER"
#define PD_VOTER "PD_VOTER"
+#define USB_PSY_VOTER "USB_PSY_VOTER"
#define PL_TAPER_WORK_RUNNING_VOTER "PL_TAPER_WORK_RUNNING_VOTER"
#define PARALLEL_PSY_VOTER "PARALLEL_PSY_VOTER"
#define PL_INDIRECT_VOTER "PL_INDIRECT_VOTER"
@@ -37,6 +38,13 @@ enum print_reason {
#define TAPER_END_VOTER "TAPER_END_VOTER"
#define FCC_MAX_RESULT_VOTER "FCC_MAX_RESULT_VOTER"
#define THERMAL_DAEMON_VOTER "THERMAL_DAEMON_VOTER"
+#define CC_DETACHED_VOTER "CC_DETACHED_VOTER"
+#define HVDCP_TIMEOUT_VOTER "HVDCP_TIMEOUT_VOTER"
+#define PD_DISALLOWED_INDIRECT_VOTER "PD_DISALLOWED_INDIRECT_VOTER"
+#define PD_HARD_RESET_VOTER "PD_HARD_RESET_VOTER"
+#define VBUS_CC_SHORT_VOTER "VBUS_CC_SHORT_VOTER"
+#define LEGACY_CABLE_VOTER "LEGACY_CABLE_VOTER"
+#define PD_INACTIVE_VOTER "PD_INACTIVE_VOTER"
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -89,13 +97,14 @@ struct smb_params {
struct smb_chg_param step_soc_threshold[4];
struct smb_chg_param step_soc;
struct smb_chg_param step_cc_delta[5];
+ struct smb_chg_param freq_buck;
};
struct parallel_params {
struct power_supply *psy;
- int *master_percent;
- int taper_percent;
- int slave_fcc;
+ int slave_pct;
+ int taper_pct;
+ int slave_fcc_ua;
};
struct smb_iio {
@@ -108,6 +117,7 @@ struct smb_iio {
struct smb_charger {
struct device *dev;
+ char *name;
struct regmap *regmap;
struct smb_params param;
struct smb_iio iio;
@@ -144,11 +154,14 @@ struct smb_charger {
struct votable *fv_votable;
struct votable *usb_icl_votable;
struct votable *dc_icl_votable;
+ struct votable *pd_disallowed_votable_indirect;
struct votable *pd_allowed_votable;
struct votable *awake_votable;
struct votable *pl_disable_votable;
struct votable *chg_disable_votable;
struct votable *pl_enable_votable_indirect;
+ struct votable *hvdcp_disable_votable;
+ struct votable *apsd_disable_votable;
/* work */
struct work_struct bms_update_work;
@@ -162,8 +175,9 @@ struct smb_charger {
/* cached status */
int voltage_min_uv;
int voltage_max_uv;
- bool pd_active;
+ int pd_active;
bool vbus_present;
+ bool system_suspend_supported;
int system_temp_level;
int thermal_levels;
@@ -276,6 +290,8 @@ int smblib_get_prop_usb_suspend(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_pd_current_max(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_usb_current_max(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
@@ -290,10 +306,14 @@ int smblib_get_prop_pd_allowed(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_input_current_settled(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_pd_in_hard_reset(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_charger_temp(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_charger_temp_max(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_set_prop_pd_current_max(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_set_prop_usb_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
@@ -304,6 +324,8 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_pd_active(struct smb_charger *chg,
const union power_supply_propval *val);
+int smblib_set_prop_pd_in_hard_reset(struct smb_charger *chg,
+ const union power_supply_propval *val);
int smblib_get_prop_slave_current_now(struct smb_charger *chg,
union power_supply_propval *val);
@@ -311,4 +333,3 @@ int smblib_get_prop_slave_current_now(struct smb_charger *chg,
int smblib_init(struct smb_charger *chg);
int smblib_deinit(struct smb_charger *chg);
#endif /* __SMB2_CHARGER_H */
-
diff --git a/drivers/power/qcom-charger/smb-reg.h b/drivers/power/qcom-charger/smb-reg.h
index 8a49a8fb38ba..ba501761c209 100644
--- a/drivers/power/qcom-charger/smb-reg.h
+++ b/drivers/power/qcom-charger/smb-reg.h
@@ -52,6 +52,7 @@ enum {
#define CHARGER_ERROR_STATUS_BAT_OV_BIT BIT(5)
#define CHARGER_ERROR_STATUS_BAT_TERM_MISSING_BIT BIT(4)
#define BAT_TEMP_STATUS_MASK GENMASK(3, 0)
+#define BAT_TEMP_STATUS_SOFT_LIMIT_MASK GENMASK(3, 2)
#define BAT_TEMP_STATUS_HOT_SOFT_LIMIT_BIT BIT(3)
#define BAT_TEMP_STATUS_COLD_SOFT_LIMIT_BIT BIT(2)
#define BAT_TEMP_STATUS_TOO_HOT_BIT BIT(1)
@@ -506,6 +507,15 @@ enum {
#define CC_ORIENTATION_BIT BIT(1)
#define CC_ATTACHED_BIT BIT(0)
+#define TYPE_C_STATUS_5_REG (USBIN_BASE + 0x0F)
+#define TRY_SOURCE_FAILED_BIT BIT(6)
+#define TRY_SINK_FAILED_BIT BIT(5)
+#define TIMER_STAGE_2_BIT BIT(4)
+#define TYPEC_LEGACY_CABLE_STATUS_BIT BIT(3)
+#define TYPEC_NONCOMP_LEGACY_CABLE_STATUS_BIT BIT(2)
+#define TYPEC_TRYSOURCE_DETECT_STATUS_BIT BIT(1)
+#define TYPEC_TRYSINK_DETECT_STATUS_BIT BIT(0)
+
/* USBIN Interrupt Bits */
#define TYPE_C_CHANGE_RT_STS_BIT BIT(7)
#define USBIN_ICL_CHANGE_RT_STS_BIT BIT(6)
@@ -555,6 +565,16 @@ enum {
#define TYPE_C_UFP_MODE_BIT BIT(1)
#define EN_80UA_180UA_CUR_SOURCE_BIT BIT(0)
+#define TYPE_C_CFG_3_REG (USBIN_BASE + 0x5A)
+#define TVBUS_DEBOUNCE_BIT BIT(7)
+#define TYPEC_LEGACY_CABLE_INT_EN_BIT BIT(6)
+#define TYPEC_NONCOMPLIANT_LEGACY_CABLE_INT_EN_BIT BIT(5)
+#define TYPEC_TRYSOURCE_DETECT_INT_EN_BIT BIT(4)
+#define TYPEC_TRYSINK_DETECT_INT_EN_BIT BIT(3)
+#define EN_TRYSINK_MODE_BIT BIT(2)
+#define EN_LEGACY_CABLE_DETECTION_BIT BIT(1)
+#define ALLOW_PD_DRING_UFP_TCCDB_BIT BIT(0)
+
#define USBIN_ADAPTER_ALLOW_CFG_REG (USBIN_BASE + 0x60)
#define USBIN_ADAPTER_ALLOW_MASK GENMASK(3, 0)
enum {
@@ -585,6 +605,7 @@ enum {
#define DCD_TIMEOUT_SEL_BIT BIT(5)
#define OCD_CURRENT_SEL_BIT BIT(4)
#define SLOW_PLUGIN_TIMER_EN_CFG_BIT BIT(3)
+#define FLOAT_OPTIONS_MASK GENMASK(2, 0)
#define FLOAT_DIS_CHGING_CFG_BIT BIT(2)
#define SUSPEND_FLOAT_CFG_BIT BIT(1)
#define FORCE_FLOAT_SDP_CFG_BIT BIT(0)
@@ -612,7 +633,7 @@ enum {
#define TYPEC_VBUS_ASSERT_INT_EN_BIT BIT(0)
#define TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG (USBIN_BASE + 0x68)
-#define EXIT_SNK_BASED_ON_CC BIT(7)
+#define EXIT_SNK_BASED_ON_CC_BIT BIT(7)
#define VCONN_EN_ORIENTATION_BIT BIT(6)
#define TYPEC_VCONN_OVERCURR_INT_EN_BIT BIT(5)
#define VCONN_EN_SRC_BIT BIT(4)
@@ -975,4 +996,6 @@ enum {
#define SYSOK_POL_BIT BIT(3)
#define SYSOK_OPTIONS_MASK GENMASK(2, 0)
+#define CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG (MISC_BASE + 0xA0)
+
#endif /* __SMB2_CHARGER_REG_H */
diff --git a/drivers/power/qcom-charger/smb138x-charger.c b/drivers/power/qcom-charger/smb138x-charger.c
index e8ec2f49f7eb..3db295b3e6e8 100644
--- a/drivers/power/qcom-charger/smb138x-charger.c
+++ b/drivers/power/qcom-charger/smb138x-charger.c
@@ -72,6 +72,13 @@ static struct smb_params v1_params = {
.max_u = 6000000,
.step_u = 25000,
},
+ .freq_buck = {
+ .name = "buck switching frequency",
+ .reg = CFG_BUCKBOOST_FREQ_SELECT_BUCK_REG,
+ .min_u = 500,
+ .max_u = 2000,
+ .step_u = 100,
+ },
};
struct smb_dt_props {
@@ -471,6 +478,10 @@ static int smb138x_parallel_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_set_charge_param(chg, &chg->param.fcc, val->intval);
break;
+ case POWER_SUPPLY_PROP_BUCK_FREQ:
+ rc = smblib_set_charge_param(chg, &chg->param.freq_buck,
+ val->intval);
+ break;
default:
pr_err("parallel power supply set prop %d not supported\n",
prop);
@@ -1172,6 +1183,7 @@ static int smb138x_probe(struct platform_device *pdev)
chip->chg.dev = &pdev->dev;
chip->chg.debug_mask = &__debug_mask;
+ chip->chg.name = "SMB";
chip->chg.regmap = dev_get_regmap(chip->chg.dev->parent, NULL);
if (!chip->chg.regmap) {