Loading drivers/power/supply/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading drivers/power/supply/qti_battery_charger.c +110 −1 Original line number Diff line number Diff line // 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__ Loading @@ -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> Loading Loading @@ -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, Loading Loading @@ -106,6 +112,8 @@ enum usb_property_id { USB_TEMP, USB_REAL_TYPE, USB_TYPEC_COMPLIANT, USB_SCOPE, USB_CONNECTOR_TYPE, USB_PROP_MAX, }; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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] = { Loading @@ -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", Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -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[] = { Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading
drivers/power/supply/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/power/supply/qti_battery_charger.c +110 −1 Original line number Diff line number Diff line // 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__ Loading @@ -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> Loading Loading @@ -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, Loading Loading @@ -106,6 +112,8 @@ enum usb_property_id { USB_TEMP, USB_REAL_TYPE, USB_TYPEC_COMPLIANT, USB_SCOPE, USB_CONNECTOR_TYPE, USB_PROP_MAX, }; Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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] = { Loading @@ -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", Loading Loading @@ -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) Loading Loading @@ -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, Loading Loading @@ -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[] = { Loading Loading @@ -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; Loading Loading @@ -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; Loading