mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 12:25:00 -04:00
Merge "power: supply: qti_battery_charger: update USB power supply type runtime"
This commit is contained in:
commit
734fd627ac
1 changed files with 226 additions and 4 deletions
|
|
@ -47,6 +47,7 @@
|
|||
#define WLS_FW_PREPARE_TIME_MS 300
|
||||
#define WLS_FW_WAIT_TIME_MS 500
|
||||
#define WLS_FW_BUF_SIZE 128
|
||||
#define DEFAULT_RESTRICT_FCC_UA 1000000
|
||||
|
||||
enum psy_type {
|
||||
PSY_TYPE_BATTERY,
|
||||
|
|
@ -100,6 +101,9 @@ enum usb_property_id {
|
|||
USB_ADAP_TYPE,
|
||||
USB_MOISTURE_DET_EN,
|
||||
USB_MOISTURE_DET_STS,
|
||||
USB_TEMP,
|
||||
USB_REAL_TYPE,
|
||||
USB_TYPEC_COMPLIANT,
|
||||
USB_PROP_MAX,
|
||||
};
|
||||
|
||||
|
|
@ -114,6 +118,12 @@ enum wireless_property_id {
|
|||
WLS_PROP_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
QTI_POWER_SUPPLY_USB_TYPE_HVDCP = 0x80,
|
||||
QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3,
|
||||
QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5,
|
||||
};
|
||||
|
||||
struct battery_charger_set_notify_msg {
|
||||
struct pmic_glink_hdr hdr;
|
||||
u32 battery_id;
|
||||
|
|
@ -214,6 +224,7 @@ struct battery_chg_dev {
|
|||
int num_thermal_levels;
|
||||
atomic_t state;
|
||||
struct work_struct subsys_up_work;
|
||||
struct work_struct usb_type_work;
|
||||
int fake_soc;
|
||||
bool block_tx;
|
||||
bool ship_mode_en;
|
||||
|
|
@ -221,6 +232,9 @@ struct battery_chg_dev {
|
|||
bool wls_fw_update_reqd;
|
||||
u32 wls_fw_version;
|
||||
struct notifier_block reboot_notifier;
|
||||
u32 thermal_fcc_ua;
|
||||
u32 restrict_fcc_ua;
|
||||
bool restrict_chg_en;
|
||||
};
|
||||
|
||||
static const int battery_prop_map[BATT_PROP_MAX] = {
|
||||
|
|
@ -256,6 +270,7 @@ static const int usb_prop_map[USB_PROP_MAX] = {
|
|||
[USB_CURR_MAX] = POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
[USB_INPUT_CURR_LIMIT] = POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
|
||||
[USB_ADAP_TYPE] = POWER_SUPPLY_PROP_USB_TYPE,
|
||||
[USB_TEMP] = POWER_SUPPLY_PROP_TEMP,
|
||||
};
|
||||
|
||||
static const int wls_prop_map[WLS_PROP_MAX] = {
|
||||
|
|
@ -266,6 +281,17 @@ static const int wls_prop_map[WLS_PROP_MAX] = {
|
|||
[WLS_CURR_MAX] = POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
};
|
||||
|
||||
/* Standard usb_type definitions similar to power_supply_sysfs.c */
|
||||
static const char * const power_supply_usb_type_text[] = {
|
||||
"Unknown", "SDP", "DCP", "CDP", "ACA", "C",
|
||||
"PD", "PD_DRP", "PD_PPS", "BrickID"
|
||||
};
|
||||
|
||||
/* Custom usb_type definitions */
|
||||
static const char * const qc_power_supply_usb_type_text[] = {
|
||||
"HVDCP", "HVDCP_3", "HVDCP_3P5"
|
||||
};
|
||||
|
||||
static int battery_chg_fw_write(struct battery_chg_dev *bcdev, void *data,
|
||||
int len)
|
||||
{
|
||||
|
|
@ -595,6 +621,54 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data,
|
|||
complete(&bcdev->ack);
|
||||
}
|
||||
|
||||
static struct power_supply_desc usb_psy_desc;
|
||||
|
||||
static void battery_chg_update_usb_type_work(struct work_struct *work)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(work,
|
||||
struct battery_chg_dev, usb_type_work);
|
||||
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
|
||||
int rc;
|
||||
|
||||
rc = read_property_id(bcdev, pst, USB_ADAP_TYPE);
|
||||
if (rc < 0) {
|
||||
pr_err("Failed to read USB_ADAP_TYPE rc=%d\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("usb_adap_type: %u\n", pst->prop[USB_ADAP_TYPE]);
|
||||
|
||||
switch (pst->prop[USB_ADAP_TYPE]) {
|
||||
case POWER_SUPPLY_USB_TYPE_SDP:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_DCP:
|
||||
case POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID:
|
||||
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP:
|
||||
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3:
|
||||
case QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_DCP;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_CDP:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_CDP;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_ACA:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_ACA;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_C:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_TYPE_C;
|
||||
break;
|
||||
case POWER_SUPPLY_USB_TYPE_PD:
|
||||
case POWER_SUPPLY_USB_TYPE_PD_DRP:
|
||||
case POWER_SUPPLY_USB_TYPE_PD_PPS:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB_PD;
|
||||
break;
|
||||
default:
|
||||
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_notification(struct battery_chg_dev *bcdev, void *data,
|
||||
size_t len)
|
||||
{
|
||||
|
|
@ -615,6 +689,7 @@ static void handle_notification(struct battery_chg_dev *bcdev, void *data,
|
|||
break;
|
||||
case BC_USB_STATUS_GET:
|
||||
pst = &bcdev->psy_list[PSY_TYPE_USB];
|
||||
schedule_work(&bcdev->usb_type_work);
|
||||
break;
|
||||
case BC_WLS_STATUS_GET:
|
||||
pst = &bcdev->psy_list[PSY_TYPE_WLS];
|
||||
|
|
@ -707,6 +782,28 @@ static const struct power_supply_desc wls_psy_desc = {
|
|||
.property_is_writeable = wls_psy_prop_is_writeable,
|
||||
};
|
||||
|
||||
static const char *get_usb_type_name(u32 usb_type)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
if (usb_type >= QTI_POWER_SUPPLY_USB_TYPE_HVDCP &&
|
||||
usb_type <= QTI_POWER_SUPPLY_USB_TYPE_HVDCP_3P5) {
|
||||
for (i = 0; i < ARRAY_SIZE(qc_power_supply_usb_type_text);
|
||||
i++) {
|
||||
if (i == (usb_type - QTI_POWER_SUPPLY_USB_TYPE_HVDCP))
|
||||
return qc_power_supply_usb_type_text[i];
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(power_supply_usb_type_text); i++) {
|
||||
if (i == usb_type)
|
||||
return power_supply_usb_type_text[i];
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static int usb_psy_set_icl(struct battery_chg_dev *bcdev, u32 prop_id, int val)
|
||||
{
|
||||
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
|
||||
|
|
@ -758,6 +855,8 @@ static int usb_psy_get_prop(struct power_supply *psy,
|
|||
return rc;
|
||||
|
||||
pval->intval = pst->prop[prop_id];
|
||||
if (prop == POWER_SUPPLY_PROP_TEMP)
|
||||
pval->intval = DIV_ROUND_CLOSEST((int)pval->intval, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -806,6 +905,7 @@ static enum power_supply_property usb_props[] = {
|
|||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
|
||||
POWER_SUPPLY_PROP_USB_TYPE,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
};
|
||||
|
||||
static enum power_supply_usb_type usb_psy_supported_types[] = {
|
||||
|
|
@ -821,7 +921,7 @@ static enum power_supply_usb_type usb_psy_supported_types[] = {
|
|||
POWER_SUPPLY_USB_TYPE_APPLE_BRICK_ID,
|
||||
};
|
||||
|
||||
static const struct power_supply_desc usb_psy_desc = {
|
||||
static struct power_supply_desc usb_psy_desc = {
|
||||
.name = "usb",
|
||||
.type = POWER_SUPPLY_TYPE_USB,
|
||||
.properties = usb_props,
|
||||
|
|
@ -833,6 +933,26 @@ static const struct power_supply_desc usb_psy_desc = {
|
|||
.property_is_writeable = usb_psy_prop_is_writeable,
|
||||
};
|
||||
|
||||
static int __battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
|
||||
u32 fcc_ua)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (bcdev->restrict_chg_en)
|
||||
fcc_ua = min_t(u32, fcc_ua, bcdev->thermal_fcc_ua);
|
||||
else
|
||||
fcc_ua = bcdev->thermal_fcc_ua;
|
||||
|
||||
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY],
|
||||
BATT_CHG_CTRL_LIM, fcc_ua);
|
||||
if (rc < 0)
|
||||
pr_err("Failed to set FCC %u, rc=%d\n", fcc_ua, rc);
|
||||
else
|
||||
pr_debug("Set FCC to %u uA\n", fcc_ua);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
|
||||
int val)
|
||||
{
|
||||
|
|
@ -852,11 +972,10 @@ static int battery_psy_set_charge_current(struct battery_chg_dev *bcdev,
|
|||
|
||||
fcc_ua = bcdev->thermal_levels[val];
|
||||
|
||||
rc = write_property_id(bcdev, &bcdev->psy_list[PSY_TYPE_BATTERY],
|
||||
BATT_CHG_CTRL_LIM, fcc_ua);
|
||||
rc = __battery_psy_set_charge_current(bcdev, fcc_ua);
|
||||
if (!rc) {
|
||||
bcdev->curr_thermal_level = val;
|
||||
pr_debug("Set FCC to %u uA\n", fcc_ua);
|
||||
bcdev->thermal_fcc_ua = fcc_ua;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
|
@ -1232,6 +1351,102 @@ static ssize_t wireless_fw_update_store(struct class *c,
|
|||
}
|
||||
static CLASS_ATTR_WO(wireless_fw_update);
|
||||
|
||||
static ssize_t usb_typec_compliant_show(struct class *c,
|
||||
struct class_attribute *attr, char *buf)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
|
||||
int rc;
|
||||
|
||||
rc = read_property_id(bcdev, pst, USB_TYPEC_COMPLIANT);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n",
|
||||
(int)pst->prop[USB_TYPEC_COMPLIANT]);
|
||||
}
|
||||
static CLASS_ATTR_RO(usb_typec_compliant);
|
||||
|
||||
static ssize_t usb_real_type_show(struct class *c,
|
||||
struct class_attribute *attr, char *buf)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
|
||||
int rc;
|
||||
|
||||
rc = read_property_id(bcdev, pst, USB_REAL_TYPE);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%s\n",
|
||||
get_usb_type_name(pst->prop[USB_REAL_TYPE]));
|
||||
}
|
||||
static CLASS_ATTR_RO(usb_real_type);
|
||||
|
||||
static ssize_t restrict_cur_store(struct class *c, struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
int rc;
|
||||
u32 val;
|
||||
|
||||
if (kstrtou32(buf, 0, &val) || val > bcdev->thermal_fcc_ua)
|
||||
return -EINVAL;
|
||||
|
||||
if (bcdev->restrict_chg_en) {
|
||||
rc = __battery_psy_set_charge_current(bcdev, val);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
bcdev->restrict_fcc_ua = val;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t restrict_cur_show(struct class *c, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%u\n", bcdev->restrict_fcc_ua);
|
||||
}
|
||||
static CLASS_ATTR_RW(restrict_cur);
|
||||
|
||||
static ssize_t restrict_chg_store(struct class *c, struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
int rc;
|
||||
bool val;
|
||||
|
||||
if (kstrtobool(buf, &val))
|
||||
return -EINVAL;
|
||||
|
||||
bcdev->restrict_chg_en = val;
|
||||
|
||||
rc = __battery_psy_set_charge_current(bcdev, bcdev->restrict_fcc_ua);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t restrict_chg_show(struct class *c, struct class_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct battery_chg_dev *bcdev = container_of(c, struct battery_chg_dev,
|
||||
battery_class);
|
||||
|
||||
return scnprintf(buf, PAGE_SIZE, "%d\n", bcdev->restrict_chg_en);
|
||||
}
|
||||
static CLASS_ATTR_RW(restrict_chg);
|
||||
|
||||
static ssize_t fake_soc_store(struct class *c, struct class_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
|
|
@ -1417,6 +1632,10 @@ static struct attribute *battery_class_attrs[] = {
|
|||
&class_attr_wireless_fw_force_update.attr,
|
||||
&class_attr_wireless_fw_version.attr,
|
||||
&class_attr_ship_mode_en.attr,
|
||||
&class_attr_restrict_chg.attr,
|
||||
&class_attr_restrict_cur.attr,
|
||||
&class_attr_usb_real_type.attr,
|
||||
&class_attr_usb_typec_compliant.attr,
|
||||
NULL,
|
||||
};
|
||||
ATTRIBUTE_GROUPS(battery_class);
|
||||
|
|
@ -1512,6 +1731,7 @@ static int battery_chg_parse_dt(struct battery_chg_dev *bcdev)
|
|||
}
|
||||
|
||||
bcdev->num_thermal_levels = len;
|
||||
bcdev->thermal_fcc_ua = pst->prop[BATT_CHG_CTRL_LIM_MAX];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1583,6 +1803,7 @@ static int battery_chg_probe(struct platform_device *pdev)
|
|||
init_completion(&bcdev->fw_buf_ack);
|
||||
init_completion(&bcdev->fw_update_ack);
|
||||
INIT_WORK(&bcdev->subsys_up_work, battery_chg_subsys_up_work);
|
||||
INIT_WORK(&bcdev->usb_type_work, battery_chg_update_usb_type_work);
|
||||
atomic_set(&bcdev->state, PMIC_GLINK_STATE_UP);
|
||||
bcdev->dev = dev;
|
||||
|
||||
|
|
@ -1609,6 +1830,7 @@ static int battery_chg_probe(struct platform_device *pdev)
|
|||
if (rc < 0)
|
||||
goto error;
|
||||
|
||||
bcdev->restrict_fcc_ua = DEFAULT_RESTRICT_FCC_UA;
|
||||
platform_set_drvdata(pdev, bcdev);
|
||||
bcdev->fake_soc = -EINVAL;
|
||||
rc = battery_chg_init_psy(bcdev);
|
||||
|
|
|
|||
Loading…
Reference in a new issue