power: qti_typec_class: Add typec class support for micro USB

Add typec class support for micro USB to show the data/power role
options in UI.

Change-Id: I83c0afa6ef9098a85d6c66e076e6a506d945c7fd
Signed-off-by: Kiran Gunda <kgunda@codeaurora.org>
This commit is contained in:
Kiran Gunda 2021-02-04 20:12:18 +05:30 • committed by Gerrit - the friendly Code Review server
commit b5b08a09f7
4 changed files with 120 additions and 1 deletions

View file

@ -92,5 +92,6 @@ obj-$(CONFIG_FUEL_GAUGE_SC27XX) += sc27xx_fuel_gauge.o
obj-$(CONFIG_CHARGER_UCS1002) += ucs1002_power.o
obj-$(CONFIG_CHARGER_BD70528) += bd70528-charger.o
obj-$(CONFIG_CHARGER_WILCO) += wilco-charger.o
obj-$(CONFIG_QTI_BATTERY_CHARGER) += qti_battery_charger.o
obj-$(CONFIG_QTI_BATTERY_CHARGER) += qti_battery_charger_main.o
qti_battery_charger_main-y += qti_battery_charger.o qti_typec_class.o
obj-$(CONFIG_QCOM_POWER_SUPPLY) += qcom/

View file

@ -20,6 +20,7 @@
#include <linux/power_supply.h>
#include <linux/soc/qcom/pmic_glink.h>
#include <linux/soc/qcom/battery_charger.h>
#include "qti_typec_class.h"
#define MSG_OWNER_BC 32778
#define MSG_TYPE_REQ_RESP 1
@ -223,6 +224,7 @@ struct battery_chg_dev {
struct device *dev;
struct class battery_class;
struct pmic_glink_client *client;
struct typec_role_class *typec_class;
struct mutex rw_lock;
struct completion ack;
struct completion fw_buf_ack;
@ -666,12 +668,21 @@ static void battery_chg_update_uusb_type(struct battery_chg_dev *bcdev,
/* Device mode connect notification */
extcon_set_state_sync(bcdev->extcon, EXTCON_USB, 1);
bcdev->usb_prev_mode = EXTCON_USB;
rc = qti_typec_partner_register(bcdev->typec_class,
TYPEC_DEVICE);
if (rc < 0)
pr_err("Failed to register typec partner rc=%d\n",
rc);
}
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;
rc = qti_typec_partner_register(bcdev->typec_class, TYPEC_HOST);
if (rc < 0)
pr_err("Failed to register typec partner rc=%d\n",
rc);
break;
default:
if (bcdev->usb_prev_mode == EXTCON_USB ||
@ -680,6 +691,7 @@ static void battery_chg_update_uusb_type(struct battery_chg_dev *bcdev,
extcon_set_state_sync(bcdev->extcon,
bcdev->usb_prev_mode, 0);
bcdev->usb_prev_mode = EXTCON_NONE;
qti_typec_partner_unregister(bcdev->typec_class);
}
break;
}
@ -2059,6 +2071,15 @@ static int battery_chg_probe(struct platform_device *pdev)
if (rc < 0)
dev_warn(dev, "Failed to register extcon rc=%d\n", rc);
if (bcdev->connector_type == USB_CONNECTOR_TYPE_MICRO_USB) {
bcdev->typec_class = qti_typec_class_init(bcdev->dev);
if (IS_ERR_OR_NULL(bcdev->typec_class)) {
dev_err(dev, "Failed to init typec class err=%d\n",
PTR_ERR(bcdev->typec_class));
return PTR_ERR(bcdev->typec_class);
}
}
schedule_work(&bcdev->usb_type_work);
return 0;
@ -2079,6 +2100,7 @@ static int battery_chg_remove(struct platform_device *pdev)
debugfs_remove_recursive(bcdev->debugfs_dir);
class_unregister(&bcdev->battery_class);
unregister_reboot_notifier(&bcdev->reboot_notifier);
qti_typec_class_deinit(bcdev->typec_class);
rc = pmic_glink_unregister_client(bcdev->client);
if (rc < 0) {
pr_err("Error unregistering from pmic_glink, rc=%d\n", rc);

View file

@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021, The Linux Foundation. All rights reserved.
*/
#include <linux/device.h>
#include <linux/slab.h>
#include "qti_typec_class.h"
int qti_typec_partner_register(struct typec_role_class *chip, int mode)
{
if (!chip || !chip->typec_port)
return -ENODEV;
if (!chip->typec_partner) {
chip->typec_partner = typec_register_partner(chip->typec_port,
&chip->typec_partner_desc);
if (IS_ERR_OR_NULL(chip->typec_partner))
return PTR_ERR(chip->typec_partner);
}
if (mode == TYPEC_DEVICE) {
typec_set_data_role(chip->typec_port, TYPEC_DEVICE);
typec_set_pwr_role(chip->typec_port, TYPEC_SINK);
} else {
typec_set_data_role(chip->typec_port, TYPEC_HOST);
typec_set_pwr_role(chip->typec_port, TYPEC_SOURCE);
}
return 0;
}
void qti_typec_partner_unregister(struct typec_role_class *chip)
{
if (!chip || !chip->typec_port)
return;
if (chip->typec_partner) {
typec_unregister_partner(chip->typec_partner);
chip->typec_partner = NULL;
}
}
struct typec_role_class *qti_typec_class_init(struct device *dev)
{
struct typec_role_class *chip;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (!chip)
return ERR_PTR(-ENOMEM);
chip->typec_caps.type = TYPEC_PORT_DRP;
chip->typec_caps.data = TYPEC_PORT_DRD;
chip->typec_caps.revision = 0x0130;
chip->typec_partner_desc.usb_pd = false;
chip->typec_partner_desc.accessory = TYPEC_ACCESSORY_NONE;
chip->typec_port = typec_register_port(dev, &chip->typec_caps);
if (IS_ERR_OR_NULL(chip->typec_port))
return ERR_PTR(-ENODEV);
return chip;
}
void qti_typec_class_deinit(struct typec_role_class *chip)
{
if (!chip || !chip->typec_port)
return;
qti_typec_partner_unregister(chip);
typec_unregister_port(chip->typec_port);
chip->typec_port = NULL;
}

View file

@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2021 The Linux Foundation. All rights reserved.
*/
#ifndef __QTI_TYPEC_CLASS_H
#define __QTI_TYPEC_CLASS_H
#include <linux/usb/typec.h>
struct typec_role_class {
struct typec_port *typec_port;
struct typec_capability typec_caps;
struct typec_partner *typec_partner;
struct typec_partner_desc typec_partner_desc;
};
int qti_typec_partner_register(struct typec_role_class *chip, int mode);
void qti_typec_partner_unregister(struct typec_role_class *chip);
struct typec_role_class *qti_typec_class_init(struct device *dev);
void qti_typec_class_deinit(struct typec_role_class *chip);
#endif /* __QTI_TYPEC_CLASS_H */