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

Commit 7827fab3 authored by Ajay Agarwal's avatar Ajay Agarwal
Browse files

phy: msm: usb: Add USB atomic notifier for USB psy registration



Add support for USB atomic notifier callback when power supply
framework registers any power supply. Check in the callback
function if the psy registered is USB, and then register extcon
handles for VBUS and ID notifications. This helps to remove
dependency between SMB and msm_otg probe routines.

Change-Id: I4d4d98cc45ab70fc3742142a0f18fcfc84bea790
Signed-off-by: default avatarAjay Agarwal <ajaya@codeaurora.org>
parent 4090fc55
Loading
Loading
Loading
Loading
+57 −20
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <linux/pm_wakeup.h>
#include <linux/reset.h>
#include <linux/extcon.h>
#include <linux/power_supply.h>
#include <soc/qcom/scm.h>

#include <linux/usb.h>
@@ -3717,6 +3718,46 @@ static int msm_otg_extcon_register(struct msm_otg *motg)
	return ret;
}

static void msm_otg_handle_initial_extcon(struct msm_otg *motg)
{
	if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
							EXTCON_USB))
		msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);

	if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
							EXTCON_USB_HOST))
		msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
}

static void msm_otg_extcon_register_work(struct work_struct *w)
{
	struct msm_otg *motg = container_of(w, struct msm_otg,
						extcon_register_work);

	power_supply_unreg_notifier(&motg->psy_nb);

	if (msm_otg_extcon_register(motg)) {
		dev_err(&motg->pdev->dev, "failed to register extcon\n");
		return;
	}

	msm_otg_handle_initial_extcon(motg);
}

static int msm_otg_psy_changed(struct notifier_block *nb, unsigned long evt,
							void *ptr)
{
	struct msm_otg *motg = container_of(nb, struct msm_otg, psy_nb);

	if (strcmp(((struct power_supply *)ptr)->desc->name, "usb") ||
						evt != PSY_EVENT_PROP_CHANGED)
		return 0;

	queue_work(motg->otg_wq, &motg->extcon_register_work);

	return 0;
}

struct msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
	struct device_node *node = pdev->dev.of_node;
@@ -4266,6 +4307,7 @@ static int msm_otg_probe(struct platform_device *pdev)
	INIT_DELAYED_WORK(&motg->perf_vote_work, msm_otg_perf_vote_work);
	INIT_DELAYED_WORK(&motg->sdp_check, check_for_sdp_connection);
	INIT_WORK(&motg->notify_charger_work, msm_otg_notify_charger_work);
	INIT_WORK(&motg->extcon_register_work, msm_otg_extcon_register_work);
	motg->otg_wq = alloc_ordered_workqueue("k_otg", 0);
	if (!motg->otg_wq) {
		pr_err("%s: Unable to create workqueue otg_wq\n",
@@ -4474,21 +4516,20 @@ static int msm_otg_probe(struct platform_device *pdev)
		}
	}

	psy = power_supply_get_by_name("usb");
	if (!psy)
		dev_warn(&pdev->dev, "Could not get usb power_supply\n");

	/*
	 * Try to register extcon handle from probe; by this time USB psy may or
	 * may not have been registered. If this fails, then wait for the USB
	 * psy to get registered which will again try to register extcon via
	 * notifier call.
	 */
	ret = msm_otg_extcon_register(motg);
	if (ret)
		goto put_psy;

	if (motg->extcon_vbus && extcon_get_cable_state_(motg->extcon_vbus,
							EXTCON_USB))
		msm_otg_vbus_notifier(&motg->vbus_nb, true, motg->extcon_vbus);

	if (motg->extcon_id && extcon_get_cable_state_(motg->extcon_id,
							EXTCON_USB_HOST))
		msm_otg_id_notifier(&motg->id_nb, true, motg->extcon_id);
	if (ret) {
		dev_dbg(&pdev->dev, "Registering PSY notifier for extcon\n");
		motg->psy_nb.notifier_call = msm_otg_psy_changed;
		power_supply_reg_notifier(&motg->psy_nb);
	} else {
		msm_otg_handle_initial_extcon(motg);
	}

	if (gpio_is_valid(motg->pdata->hub_reset_gpio)) {
		ret = devm_gpio_request(&pdev->dev,
@@ -4528,11 +4569,6 @@ static int msm_otg_probe(struct platform_device *pdev)

	return 0;

put_psy:
	if (psy)
		power_supply_put(psy);
	if (pdev->dev.of_node)
		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
remove_cdev:
	pm_runtime_disable(&pdev->dev);
	device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
@@ -4600,7 +4636,7 @@ static int msm_otg_remove(struct platform_device *pdev)
		return -EBUSY;

	unregister_pm_notifier(&motg->pm_notify);

	power_supply_unreg_notifier(&motg->psy_nb);
	extcon_unregister_notifier(motg->extcon_id, EXTCON_USB_HOST,
							&motg->id_nb);
	extcon_unregister_notifier(motg->extcon_vbus, EXTCON_USB,
@@ -4618,6 +4654,7 @@ static int msm_otg_remove(struct platform_device *pdev)
	msm_otg_perf_vote_update(motg, false);
	cancel_work_sync(&motg->sm_work);
	cancel_work_sync(&motg->notify_charger_work);
	cancel_work_sync(&motg->extcon_register_work);
	destroy_workqueue(motg->otg_wq);

	pm_runtime_resume(&pdev->dev);
+4 −0
Original line number Diff line number Diff line
@@ -180,6 +180,8 @@ enum usb_id_state {
		nominal mode.
 * @sdp_check: SDP detection work in case of USB_FLOAT power supply
 * @notify_charger_work: Charger notification work.
 * @extcon_register_work: Extcon registration work.
 * @psy_nb: Notification callback for PSY registration.
 */
struct msm_otg {
	struct usb_phy phy;
@@ -313,6 +315,8 @@ struct msm_otg {
	struct delayed_work perf_vote_work;
	struct delayed_work sdp_check;
	struct work_struct notify_charger_work;
	struct work_struct extcon_register_work;
	struct notifier_block psy_nb;
};

struct ci13xxx_platform_data {