All of lore.kernel.org
 help / color / mirror / Atom feed
From: Guenter Roeck <linux@roeck-us.net>
To: Prashant Malani <pmalani@chromium.org>
Cc: linux-kernel@vger.kernel.org, enric.balletbo@collabora.com,
	bleung@chromium.org, groeck@chromium.org,
	Felipe Balbi <balbi@kernel.org>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	"open list:DESIGNWARE USB3 DRD IP DRIVER"
	<linux-usb@vger.kernel.org>
Subject: Re: [RFC PATCH 1/1] usb: dwc3: of-simple: Add extcon support
Date: Thu, 28 May 2020 09:21:23 -0700	[thread overview]
Message-ID: <20200528162123.GA22568@roeck-us.net> (raw)
In-Reply-To: <20200523041201.75217-2-pmalani@chromium.org>

On Fri, May 22, 2020 at 09:12:02PM -0700, Prashant Malani wrote:
> Add optional extcon notifier support to enable the hotplug / unplug of
> the underlying PHY layer devices.
> 
> If supported, the Device Tree (DT) node for the device should include an
> "extcon" property which is a phandle to an extcon DT node.
> 
> This patch is an effort to incorporate the equivalent support from the
> Rockchip dwc3 driver implementation from Chrome OS [1] to the mainline.
> 
> [1] : https://chromium.googlesource.com/chromiumos/third_party/kernel/
> +/refs/heads/chromeos-4.4/drivers/usb/dwc3/dwc3-rockchip.c
> 
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Guenter Roeck <groeck@chromium.org>
> Cc: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Signed-off-by: Prashant Malani <pmalani@chromium.org>

Couple of nitpicks, otherwise

Reviewed-by: Guenter Roeck <groeck@chromium.org>

> ---
>  drivers/usb/dwc3/dwc3-of-simple.c | 149 +++++++++++++++++++++++++++++-
>  1 file changed, 146 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
> index e64754be47b4..28bde27cd1f9 100644
> --- a/drivers/usb/dwc3/dwc3-of-simple.c
> +++ b/drivers/usb/dwc3/dwc3-of-simple.c
> @@ -11,6 +11,7 @@
>   * by Subbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
>   */
>  
> +#include <linux/extcon.h>
>  #include <linux/module.h>
>  #include <linux/kernel.h>
>  #include <linux/slab.h>
> @@ -29,8 +30,117 @@ struct dwc3_of_simple {
>  	struct reset_control	*resets;
>  	bool			pulse_resets;
>  	bool			need_reset;
> +	struct extcon_dev	*edev;
> +	struct notifier_block	nb;
> +	struct work_struct	work;
> +	/* Denotes whether child devices have been populated. */
> +	bool			populated;
> +	bool			suspended;
> +	spinlock_t		suspend_lock;
>  };
>  
> +static int dwc3_of_simple_populate(struct dwc3_of_simple *simple)
> +{
> +	struct device *dev = simple->dev;
> +	struct device_node *np = dev->of_node;
> +	int ret;
> +
> +	ret = of_platform_populate(np, NULL, NULL, dev);
> +	if (ret) {
> +		dev_err(dev, "Failed to populate dwc3 devices.\n");
> +		return ret;
> +	}
> +	simple->populated = true;
> +	return 0;
> +}
> +
> +static void dwc3_of_simple_depopulate(struct dwc3_of_simple *simple)
> +{
> +	if (simple->populated) {
> +		of_platform_depopulate(simple->dev);
> +		simple->populated = false;
> +	}
> +}
> +
> +static void dwc3_of_simple_work(struct work_struct *work)
> +{
> +	struct dwc3_of_simple *simple = container_of(work,
> +					struct dwc3_of_simple, work);
> +	struct extcon_dev *edev = simple->edev;
> +
> +	if (extcon_get_state(edev, EXTCON_USB_HOST) > 0) {
> +		if (simple->populated)
> +			return;
> +
> +		dwc3_of_simple_populate(simple);
> +	} else {
> +		if (!simple->populated)
> +			return;
> +
> +		dwc3_of_simple_depopulate(simple);
> +	}
> +}
> +
> +static int dwc3_of_simple_notifier(struct notifier_block *nb,
> +			      unsigned long event, void *ptr)

Multi-line alignment is off.

> +{
> +	struct dwc3_of_simple *simple = container_of(nb, struct dwc3_of_simple,
> +						nb);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&simple->suspend_lock, flags);
> +	if (!simple->suspended)
> +		schedule_work(&simple->work);
> +	spin_unlock_irqrestore(&simple->suspend_lock, flags);
> +
> +	return NOTIFY_OK;
> +}
> +
> +static int dwc3_of_simple_extcon_register(struct dwc3_of_simple *simple)
> +{
> +	struct device		*dev = simple->dev;
> +	struct extcon_dev	*edev;
> +	int			ret;
> +
> +	edev = extcon_get_edev_by_phandle(dev, 0);
> +	if (IS_ERR(edev)) {
> +		/* The extcon property is optional. */
> +		if (PTR_ERR(edev) == -ENODEV)
> +			return 0;
> +		if (PTR_ERR(edev) != -EPROBE_DEFER)
> +			dev_err(dev, "Couldn't get extcon device.\n");
> +		return PTR_ERR(edev);
> +	}
> +
> +	INIT_WORK(&simple->work, dwc3_of_simple_work);
> +
> +	simple->nb.notifier_call = dwc3_of_simple_notifier;
> +	ret = devm_extcon_register_notifier(dev, edev, EXTCON_USB_HOST,
> +					&simple->nb);

Same here.

> +	if (ret < 0) {
> +		dev_err(dev, "Failed to register notifier.\n");
> +		return ret;
> +	}
> +
> +	simple->edev = edev;
> +
> +	return 0;
> +}
> +
> +static void dwc3_of_simple_extcon_unregister(struct dwc3_of_simple *simple)
> +{
> +	if (!simple->edev)
> +		return;
> +
> +	/*
> +	 * We explicitly unregister the notifier to prevent races with
> +	 * the of_depopulate() call in remove().
> +	 */
> +	devm_extcon_unregister_notifier(simple->dev, simple->edev,
> +					EXTCON_USB_HOST, &simple->nb);
> +	cancel_work_sync(&simple->work);
> +}
> +
>  static int dwc3_of_simple_probe(struct platform_device *pdev)
>  {
>  	struct dwc3_of_simple	*simple;
> @@ -47,6 +157,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
>  	platform_set_drvdata(pdev, simple);
>  	simple->dev = dev;
>  
> +	spin_lock_init(&simple->suspend_lock);
> +
>  	/*
>  	 * Some controllers need to toggle the usb3-otg reset before trying to
>  	 * initialize the PHY, otherwise the PHY times out.
> @@ -87,9 +199,24 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
>  	if (ret)
>  		goto err_resetc_assert;
>  
> -	ret = of_platform_populate(np, NULL, NULL, dev);
> -	if (ret)
> +	ret = dwc3_of_simple_extcon_register(simple);
> +	if (ret < 0) {
> +		dev_warn(dev, "No extcon device found, err: %d\n", ret);
>  		goto err_clk_put;
> +	}
> +
> +	if (!simple->edev) {
> +		ret = dwc3_of_simple_populate(simple);
> +		if (ret)
> +			goto err_clk_put;
> +	} else {
> +		/*
> +		 * Populate through worker to avoid race conditions against
> +		 * action scheduled through notifier.
> +		 */
> +		if (extcon_get_state(simple->edev, EXTCON_USB_HOST) > 0)
> +			schedule_work(&simple->work);
> +	}
>  
>  	pm_runtime_set_active(dev);
>  	pm_runtime_enable(dev);
> @@ -112,7 +239,8 @@ static int dwc3_of_simple_probe(struct platform_device *pdev)
>  
>  static void __dwc3_of_simple_teardown(struct dwc3_of_simple *simple)
>  {
> -	of_platform_depopulate(simple->dev);
> +	dwc3_of_simple_extcon_unregister(simple);
> +	dwc3_of_simple_depopulate(simple);
>  
>  	clk_bulk_disable_unprepare(simple->num_clocks, simple->clks);
>  	clk_bulk_put_all(simple->num_clocks, simple->clks);
> @@ -163,6 +291,13 @@ static int __maybe_unused dwc3_of_simple_runtime_resume(struct device *dev)
>  static int __maybe_unused dwc3_of_simple_suspend(struct device *dev)
>  {
>  	struct dwc3_of_simple *simple = dev_get_drvdata(dev);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&simple->suspend_lock, flags);
> +	simple->suspended = true;
> +	spin_unlock_irqrestore(&simple->suspend_lock, flags);
> +
> +	cancel_work_sync(&simple->work);
>  
>  	if (simple->need_reset)
>  		reset_control_assert(simple->resets);
> @@ -173,10 +308,18 @@ static int __maybe_unused dwc3_of_simple_suspend(struct device *dev)
>  static int __maybe_unused dwc3_of_simple_resume(struct device *dev)
>  {
>  	struct dwc3_of_simple *simple = dev_get_drvdata(dev);
> +	unsigned long flags;
>  
>  	if (simple->need_reset)
>  		reset_control_deassert(simple->resets);
>  
> +	spin_lock_irqsave(&simple->suspend_lock, flags);
> +	simple->suspended = false;
> +	spin_unlock_irqrestore(&simple->suspend_lock, flags);
> +
> +	if (simple->edev)
> +		schedule_work(&simple->work);
> +
>  	return 0;
>  }
>  

      reply	other threads:[~2020-05-28 16:21 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-23  4:12 [RFC PATCH 0/1] usb: dwc3: Extcon hotplug support to of-simple Prashant Malani
2020-05-23  4:12 ` [RFC PATCH 1/1] usb: dwc3: of-simple: Add extcon support Prashant Malani
2020-05-28 16:21   ` Guenter Roeck [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200528162123.GA22568@roeck-us.net \
    --to=linux@roeck-us.net \
    --cc=balbi@kernel.org \
    --cc=bleung@chromium.org \
    --cc=enric.balletbo@collabora.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=groeck@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=pmalani@chromium.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.