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

Commit 4c267106 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "USB: phy: msm: Register extcon callbacks in usb_add_phy()"

parents f3c76480 4802120b
Loading
Loading
Loading
Loading
+28 −135
Original line number Original line Diff line number Diff line
@@ -3707,7 +3707,8 @@ static int msm_otg_vbus_notifier(struct notifier_block *nb, unsigned long event,
static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event,
static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event,
				void *ptr)
				void *ptr)
{
{
	struct msm_otg *motg = container_of(nb, struct msm_otg, id_nb);
	struct usb_phy *phy = container_of(nb, struct usb_phy, id_nb);
	struct msm_otg *motg = container_of(phy, struct msm_otg, phy);


	if (event)
	if (event)
		motg->id_state = USB_ID_GROUND;
		motg->id_state = USB_ID_GROUND;
@@ -3719,104 +3720,6 @@ static int msm_otg_id_notifier(struct notifier_block *nb, unsigned long event,
	return NOTIFY_DONE;
	return NOTIFY_DONE;
}
}


static int msm_otg_extcon_register(struct msm_otg *motg)
{
	struct device_node *node = motg->pdev->dev.of_node;
	struct extcon_dev *edev;
	int ret = 0;

	if (motg->extcon_registered) {
		dev_info(&motg->pdev->dev, "extcon_nb already registered\n");
		return 0;
	}

	if (!of_property_read_bool(node, "extcon"))
		return 0;

	edev = extcon_get_edev_by_phandle(&motg->pdev->dev, 0);
	if (IS_ERR(edev) && PTR_ERR(edev) != -ENODEV)
		return PTR_ERR(edev);

	if (!IS_ERR(edev)) {
		motg->extcon_vbus = edev;
		motg->vbus_nb.notifier_call = msm_otg_vbus_notifier;
		ret = extcon_register_notifier(edev, EXTCON_USB,
							&motg->vbus_nb);
		if (ret < 0) {
			dev_err(&motg->pdev->dev, "failed to register notifier for USB\n");
			return ret;
		}
	}

	if (of_count_phandle_with_args(node, "extcon", NULL) > 1) {
		edev = extcon_get_edev_by_phandle(&motg->pdev->dev, 1);
		if (IS_ERR(edev) && PTR_ERR(edev) != -ENODEV) {
			ret = PTR_ERR(edev);
			goto err;
		}
	}

	if (!IS_ERR(edev)) {
		motg->extcon_id = edev;
		motg->id_nb.notifier_call = msm_otg_id_notifier;
		ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
							&motg->id_nb);
		if (ret < 0) {
			dev_err(&motg->pdev->dev, "failed to register notifier for USB-HOST\n");
			goto err;
		}
	}
	motg->extcon_registered = true;

	return 0;
err:
	if (motg->extcon_vbus)
		extcon_unregister_notifier(motg->extcon_vbus, EXTCON_USB,
								&motg->vbus_nb);

	return ret;
}

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

	if (motg->extcon_id && extcon_get_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 msm_otg_platform_data *msm_otg_dt_to_pdata(struct platform_device *pdev)
{
{
	struct device_node *node = pdev->dev.of_node;
	struct device_node *node = pdev->dev.of_node;
@@ -4058,6 +3961,7 @@ static int msm_otg_probe(struct platform_device *pdev)
			ret = PTR_ERR(motg->phy_reset_clk);
			ret = PTR_ERR(motg->phy_reset_clk);
			goto disable_sleep_clk;
			goto disable_sleep_clk;
		}
		}
	}


	motg->phy_reset = devm_reset_control_get(&pdev->dev,
	motg->phy_reset = devm_reset_control_get(&pdev->dev,
							"phy_reset");
							"phy_reset");
@@ -4066,7 +3970,6 @@ static int msm_otg_probe(struct platform_device *pdev)
		ret = PTR_ERR(motg->phy_reset);
		ret = PTR_ERR(motg->phy_reset);
		goto disable_sleep_clk;
		goto disable_sleep_clk;
	}
	}
	}


	/*
	/*
	 * If present, phy_por_clk is used to assert/de-assert phy POR
	 * If present, phy_por_clk is used to assert/de-assert phy POR
@@ -4081,6 +3984,7 @@ static int msm_otg_probe(struct platform_device *pdev)
			ret = PTR_ERR(motg->phy_por_clk);
			ret = PTR_ERR(motg->phy_por_clk);
			goto disable_sleep_clk;
			goto disable_sleep_clk;
		}
		}
	}


	motg->phy_por_reset = devm_reset_control_get(&pdev->dev,
	motg->phy_por_reset = devm_reset_control_get(&pdev->dev,
						"phy_por_reset");
						"phy_por_reset");
@@ -4089,7 +3993,6 @@ static int msm_otg_probe(struct platform_device *pdev)
		ret = PTR_ERR(motg->phy_por_reset);
		ret = PTR_ERR(motg->phy_por_reset);
		goto disable_sleep_clk;
		goto disable_sleep_clk;
	}
	}
	}


	/*
	/*
	 * If present, phy_csr_clk is required for accessing PHY
	 * If present, phy_csr_clk is required for accessing PHY
@@ -4369,7 +4272,6 @@ 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->perf_vote_work, msm_otg_perf_vote_work);
	INIT_DELAYED_WORK(&motg->sdp_check, check_for_sdp_connection);
	INIT_DELAYED_WORK(&motg->sdp_check, check_for_sdp_connection);
	INIT_WORK(&motg->notify_charger_work, msm_otg_notify_charger_work);
	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", WQ_FREEZABLE);
	motg->otg_wq = alloc_ordered_workqueue("k_otg", WQ_FREEZABLE);
	if (!motg->otg_wq) {
	if (!motg->otg_wq) {
		pr_err("%s: Unable to create workqueue otg_wq\n",
		pr_err("%s: Unable to create workqueue otg_wq\n",
@@ -4435,6 +4337,8 @@ static int msm_otg_probe(struct platform_device *pdev)
	if (pdata->enable_sec_phy)
	if (pdata->enable_sec_phy)
		phy->flags |= ENABLE_SECONDARY_PHY;
		phy->flags |= ENABLE_SECONDARY_PHY;


	phy->vbus_nb.notifier_call = msm_otg_vbus_notifier;
	phy->id_nb.notifier_call = msm_otg_id_notifier;
	ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
	ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
	if (ret) {
	if (ret) {
		dev_err(&pdev->dev, "usb_add_phy failed\n");
		dev_err(&pdev->dev, "usb_add_phy failed\n");
@@ -4578,21 +4482,6 @@ static int msm_otg_probe(struct platform_device *pdev)
		}
		}
	}
	}


	/*
	 * 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) {
		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)) {
	if (gpio_is_valid(motg->pdata->hub_reset_gpio)) {
		ret = devm_gpio_request(&pdev->dev,
		ret = devm_gpio_request(&pdev->dev,
				motg->pdata->hub_reset_gpio,
				motg->pdata->hub_reset_gpio,
@@ -4625,6 +4514,16 @@ static int msm_otg_probe(struct platform_device *pdev)
		}
		}
	}
	}


	if (of_property_read_bool(pdev->dev.of_node, "extcon")) {
		if (extcon_get_state(motg->phy.edev, EXTCON_USB_HOST)) {
			msm_otg_vbus_notifier(&motg->phy.id_nb,
							1, motg->phy.edev);
		} else if (extcon_get_state(motg->phy.edev, EXTCON_USB)) {
			msm_otg_vbus_notifier(&motg->phy.vbus_nb,
							1, motg->phy.edev);
		}
	}

	motg->pm_notify.notifier_call = msm_otg_pm_notify;
	motg->pm_notify.notifier_call = msm_otg_pm_notify;
	register_pm_notifier(&motg->pm_notify);
	register_pm_notifier(&motg->pm_notify);
	msm_otg_dbg_log_event(phy, "OTG PROBE", motg->caps, motg->lpm_flags);
	msm_otg_dbg_log_event(phy, "OTG PROBE", motg->caps, motg->lpm_flags);
@@ -4698,11 +4597,6 @@ static int msm_otg_remove(struct platform_device *pdev)
		return -EBUSY;
		return -EBUSY;


	unregister_pm_notifier(&motg->pm_notify);
	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,
							&motg->vbus_nb);


	if (pdev->dev.of_node)
	if (pdev->dev.of_node)
		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
		msm_otg_setup_devices(pdev, motg->pdata->mode, false);
@@ -4716,7 +4610,6 @@ static int msm_otg_remove(struct platform_device *pdev)
	msm_otg_perf_vote_update(motg, false);
	msm_otg_perf_vote_update(motg, false);
	cancel_work_sync(&motg->sm_work);
	cancel_work_sync(&motg->sm_work);
	cancel_work_sync(&motg->notify_charger_work);
	cancel_work_sync(&motg->notify_charger_work);
	cancel_work_sync(&motg->extcon_register_work);
	destroy_workqueue(motg->otg_wq);
	destroy_workqueue(motg->otg_wq);


	pm_runtime_resume(&pdev->dev);
	pm_runtime_resume(&pdev->dev);
+0 −14
Original line number Original line Diff line number Diff line
@@ -178,11 +178,6 @@ enum usb_id_state {
 * @phy_irq_pending: Gets set when PHY IRQ arrives in LPM.
 * @phy_irq_pending: Gets set when PHY IRQ arrives in LPM.
 * @id_state: Indicates USBID line status.
 * @id_state: Indicates USBID line status.
 * @rm_pulldown: Indicates pulldown status on D+ and D- data lines.
 * @rm_pulldown: Indicates pulldown status on D+ and D- data lines.
 * @extcon_vbus: Used for VBUS notification registration.
 * @extcon_id: Used for ID notification registration.
 * @vbus_nb: Notification callback for VBUS event.
 * @id_nb: Notification callback for ID event.
 * @extcon_registered: indicates if extcon notifier registered or not.
 * @dpdm_desc: Regulator descriptor for D+ and D- voting.
 * @dpdm_desc: Regulator descriptor for D+ and D- voting.
 * @dpdm_rdev: Regulator class device for dpdm regulator.
 * @dpdm_rdev: Regulator class device for dpdm regulator.
 * @dbg_idx: Dynamic debug buffer Index.
 * @dbg_idx: Dynamic debug buffer Index.
@@ -192,8 +187,6 @@ enum usb_id_state {
		nominal mode.
		nominal mode.
 * @sdp_check: SDP detection work in case of USB_FLOAT power supply
 * @sdp_check: SDP detection work in case of USB_FLOAT power supply
 * @notify_charger_work: Charger notification work.
 * @notify_charger_work: Charger notification work.
 * @extcon_register_work: Extcon registration work.
 * @psy_nb: Notification callback for PSY registration.
 */
 */
struct msm_otg {
struct msm_otg {
	struct usb_phy phy;
	struct usb_phy phy;
@@ -305,11 +298,6 @@ struct msm_otg {
	bool phy_irq_pending;
	bool phy_irq_pending;
	enum usb_id_state id_state;
	enum usb_id_state id_state;
	bool rm_pulldown;
	bool rm_pulldown;
	struct extcon_dev       *extcon_vbus;
	struct extcon_dev       *extcon_id;
	struct notifier_block   vbus_nb;
	struct notifier_block   id_nb;
	bool			extcon_registered;
	struct regulator_desc	dpdm_rdesc;
	struct regulator_desc	dpdm_rdesc;
	struct regulator_dev	*dpdm_rdev;
	struct regulator_dev	*dpdm_rdev;
/* Maximum debug message length */
/* Maximum debug message length */
@@ -328,8 +316,6 @@ struct msm_otg {
	struct delayed_work perf_vote_work;
	struct delayed_work perf_vote_work;
	struct delayed_work sdp_check;
	struct delayed_work sdp_check;
	struct work_struct notify_charger_work;
	struct work_struct notify_charger_work;
	struct work_struct extcon_register_work;
	struct notifier_block psy_nb;
	bool enable_sdp_check_timer;
	bool enable_sdp_check_timer;
};
};