Merge "power: supply: qti_battery_charger: Add extcon support"

This commit is contained in:
qctecmdr 2021-03-23 09:33:14 -07:00 • committed by Gerrit - the friendly Code Review server
commit 974aae1fea
2 changed files with 111 additions and 2 deletions

View file

@ -407,7 +407,7 @@ config BATTERY_TWL4030_MADC
config QTI_BATTERY_CHARGER
tristate "QTI Glink battery charger"
depends on QTI_PMIC_GLINK
depends on QTI_PMIC_GLINK && EXTCON
help
Say Y here to enable Qualcomm Technologies, Inc. battery charger
driver which interfaces with the charger firmware running on the

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
*/
#define pr_fmt(fmt) "BATTERY_CHG: %s: " fmt, __func__
@ -8,6 +8,7 @@
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/extcon-provider.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include <linux/of.h>
@ -51,6 +52,11 @@
#define WLS_FW_BUF_SIZE 128
#define DEFAULT_RESTRICT_FCC_UA 1000000
enum usb_connector_type {
USB_CONNECTOR_TYPE_TYPEC,
USB_CONNECTOR_TYPE_MICRO_USB,
};
enum psy_type {
PSY_TYPE_BATTERY,
PSY_TYPE_USB,
@ -106,6 +112,8 @@ enum usb_property_id {
USB_TEMP,
USB_REAL_TYPE,
USB_TYPEC_COMPLIANT,
USB_SCOPE,
USB_CONNECTOR_TYPE,
USB_PROP_MAX,
};
@ -221,6 +229,8 @@ struct battery_chg_dev {
struct completion fw_update_ack;
struct psy_state psy_list[PSY_TYPE_MAX];
struct dentry *debugfs_dir;
/* extcon for VBUS/ID notification for USB for micro USB */
struct extcon_dev *extcon;
u32 *thermal_levels;
const char *wls_fw_name;
int curr_thermal_level;
@ -240,6 +250,8 @@ struct battery_chg_dev {
u32 restrict_fcc_ua;
u32 last_fcc_ua;
u32 usb_icl_ua;
u32 connector_type;
u32 usb_prev_mode;
bool restrict_chg_en;
/* To track the driver initialization status */
bool initialized;
@ -279,6 +291,7 @@ static const int usb_prop_map[USB_PROP_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,
[USB_SCOPE] = POWER_SUPPLY_PROP_SCOPE,
};
static const int wls_prop_map[WLS_PROP_MAX] = {
@ -289,6 +302,12 @@ static const int wls_prop_map[WLS_PROP_MAX] = {
[WLS_CURR_MAX] = POWER_SUPPLY_PROP_CURRENT_MAX,
};
static const unsigned int bcdev_usb_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
EXTCON_NONE,
};
/* 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",
@ -624,6 +643,48 @@ static void handle_message(struct battery_chg_dev *bcdev, void *data,
complete(&bcdev->ack);
}
static void battery_chg_update_uusb_type(struct battery_chg_dev *bcdev,
u32 adap_type)
{
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
/* Handle the extcon notification for uUSB case only */
if (bcdev->connector_type != USB_CONNECTOR_TYPE_MICRO_USB)
return;
rc = read_property_id(bcdev, pst, USB_SCOPE);
if (rc < 0) {
pr_err("Failed to read USB_SCOPE rc=%d\n", rc);
return;
}
switch (pst->prop[USB_SCOPE]) {
case POWER_SUPPLY_SCOPE_DEVICE:
if (adap_type == POWER_SUPPLY_USB_TYPE_SDP ||
adap_type == POWER_SUPPLY_USB_TYPE_CDP) {
/* Device mode connect notification */
extcon_set_state_sync(bcdev->extcon, EXTCON_USB, 1);
bcdev->usb_prev_mode = EXTCON_USB;
}
break;
case POWER_SUPPLY_SCOPE_SYSTEM:
/* Host mode connect notification */
extcon_set_state_sync(bcdev->extcon, EXTCON_USB_HOST, 1);
bcdev->usb_prev_mode = EXTCON_USB_HOST;
break;
default:
if (bcdev->usb_prev_mode == EXTCON_USB ||
bcdev->usb_prev_mode == EXTCON_USB_HOST) {
/* Disconnect notification */
extcon_set_state_sync(bcdev->extcon,
bcdev->usb_prev_mode, 0);
bcdev->usb_prev_mode = EXTCON_NONE;
}
break;
}
}
static struct power_supply_desc usb_psy_desc;
static void battery_chg_update_usb_type_work(struct work_struct *work)
@ -675,6 +736,8 @@ static void battery_chg_update_usb_type_work(struct work_struct *work)
usb_psy_desc.type = POWER_SUPPLY_TYPE_USB;
break;
}
battery_chg_update_uusb_type(bcdev, pst->prop[USB_ADAP_TYPE]);
}
static void handle_notification(struct battery_chg_dev *bcdev, void *data,
@ -927,6 +990,7 @@ static enum power_supply_property usb_props[] = {
POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
POWER_SUPPLY_PROP_USB_TYPE,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_SCOPE,
};
static enum power_supply_usb_type usb_psy_supported_types[] = {
@ -1860,6 +1924,47 @@ static int battery_chg_ship_mode(struct notifier_block *nb, unsigned long code,
return NOTIFY_DONE;
}
static int register_extcon_conn_type(struct battery_chg_dev *bcdev)
{
struct psy_state *pst = &bcdev->psy_list[PSY_TYPE_USB];
int rc;
rc = read_property_id(bcdev, pst, USB_CONNECTOR_TYPE);
if (rc < 0) {
pr_err("Failed to read prop USB_CONNECTOR_TYPE, rc=%d\n",
rc);
return rc;
}
if (pst->prop[USB_CONNECTOR_TYPE] != USB_CONNECTOR_TYPE_MICRO_USB)
return 0;
bcdev->connector_type = USB_CONNECTOR_TYPE_MICRO_USB;
bcdev->usb_prev_mode = EXTCON_NONE;
bcdev->extcon = devm_extcon_dev_allocate(bcdev->dev,
bcdev_usb_extcon_cable);
if (IS_ERR(bcdev->extcon)) {
rc = PTR_ERR(bcdev->extcon);
pr_err("Failed to allocate extcon device rc=%d\n", rc);
return rc;
}
rc = devm_extcon_dev_register(bcdev->dev, bcdev->extcon);
if (rc < 0) {
pr_err("Failed to register extcon device rc=%d\n", rc);
return rc;
}
rc = extcon_set_property_capability(bcdev->extcon, EXTCON_USB,
EXTCON_PROP_USB_SS);
rc |= extcon_set_property_capability(bcdev->extcon,
EXTCON_USB_HOST, EXTCON_PROP_USB_SS);
if (rc < 0)
pr_err("failed to configure extcon capabilities rc=%d\n", rc);
return rc;
}
static int battery_chg_probe(struct platform_device *pdev)
{
struct battery_chg_dev *bcdev;
@ -1950,6 +2055,10 @@ static int battery_chg_probe(struct platform_device *pdev)
battery_chg_add_debugfs(bcdev);
battery_chg_notify_enable(bcdev);
device_init_wakeup(bcdev->dev, true);
rc = register_extcon_conn_type(bcdev);
if (rc < 0)
dev_warn(dev, "Failed to register extcon rc=%d\n", rc);
schedule_work(&bcdev->usb_type_work);
return 0;