Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5b08a09 authored by Kiran Gunda's avatar Kiran Gunda Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarKiran Gunda <kgunda@codeaurora.org>
parent 6e9701d9
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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/
+22 −0
Original line number Diff line number Diff line
@@ -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);
+75 −0
Original line number Diff line number Diff line
// 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;
}
+21 −0
Original line number Diff line number Diff line
/* 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 */