mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/5] dwc2: improve gadget support
@ 2020-12-16 20:45 Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing Michael Grzeschik
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

This series adds support for clk and reset controller defined by dts. It also
enables the hardware force mode for the gadget in case the
otg.mode="peripheral" is set.

Michael Grzeschik (5):
  usb: dwc2: cleanup on error for deferred probing
  usb: dwc2: add clk dependency for probe via oftree
  usb: dwc2: add reset controller dependency for probe via oftree
  usb: dwc2: update the dr_mode on set_mode callback
  usb: dwc2: add support to force gadget mode

 drivers/usb/dwc2/core.h   |   1 +
 drivers/usb/dwc2/dwc2.c   |  33 ++++++++-
 drivers/usb/dwc2/gadget.c | 144 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 175 insertions(+), 3 deletions(-)

-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing
  2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
@ 2020-12-16 20:45 ` Michael Grzeschik
  2020-12-17 11:00   ` Jules Maselbas
  2020-12-16 20:45 ` [PATCH 2/5] usb: dwc2: add clk dependency for probe via oftree Michael Grzeschik
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

The driver needs to cleanup the resources if an error occurred. Otherwise,
on deferred probing, it will fail to take the resources for a second time.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/usb/dwc2/dwc2.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
index bd33334a83..87d0ec7a5a 100644
--- a/drivers/usb/dwc2/dwc2.c
+++ b/drivers/usb/dwc2/dwc2.c
@@ -53,7 +53,7 @@ static int dwc2_probe(struct device_d *dev)
 	dwc2->phy = phy_optional_get(dev, "usb2-phy");
 	if (IS_ERR(dwc2->phy)) {
 		ret = PTR_ERR(dwc2->phy);
-		return ret;
+		goto release_region;
 	}
 
 	ret = phy_init(dwc2->phy);
@@ -100,7 +100,8 @@ error:
 	phy_power_off(dwc2->phy);
 err_phy_power:
 	phy_exit(dwc2->phy);
-err_phy_init:
+release_region:
+	release_region(iores);
 
 	return ret;
 }
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/5] usb: dwc2: add clk dependency for probe via oftree
  2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing Michael Grzeschik
@ 2020-12-16 20:45 ` Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 3/5] usb: dwc2: add reset controller " Michael Grzeschik
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

The dwc2 controller at least needs one core clock which needs to be
enabled before it is able to address the core registers. This patch adds
the referenced clock in the devicetree to be used.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/usb/dwc2/core.h |  1 +
 drivers/usb/dwc2/dwc2.c | 19 +++++++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index b9845b5524..780efb262c 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -467,6 +467,7 @@ struct dwc2 {
 	struct dwc2_core_params params;
 
 	struct phy *phy; /* optional */
+	struct clk *clk;
 
 #ifdef CONFIG_USB_DWC2_HOST
 	struct usb_host host;
diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
index 87d0ec7a5a..13455479ef 100644
--- a/drivers/usb/dwc2/dwc2.c
+++ b/drivers/usb/dwc2/dwc2.c
@@ -50,15 +50,26 @@ static int dwc2_probe(struct device_d *dev)
 	dwc2->regs = IOMEM(iores->start);
 	dwc2->dev = dev;
 
+	dwc2->clk = clk_get(dev, NULL);
+	if (IS_ERR(dwc2->clk)) {
+		ret = PTR_ERR(dwc2->clk);
+		dev_err(dev, "Failed to get USB clock %d\n", ret);
+		goto release_region;
+	}
+
+	ret = clk_enable(dwc2->clk);
+	if (ret)
+		goto clk_put;
+
 	dwc2->phy = phy_optional_get(dev, "usb2-phy");
 	if (IS_ERR(dwc2->phy)) {
 		ret = PTR_ERR(dwc2->phy);
-		goto release_region;
+		goto clk_disable;
 	}
 
 	ret = phy_init(dwc2->phy);
 	if (ret)
-		goto err_phy_init;
+		goto clk_disable;
 	ret = phy_power_on(dwc2->phy);
 	if (ret)
 		goto err_phy_power;
@@ -100,6 +111,10 @@ error:
 	phy_power_off(dwc2->phy);
 err_phy_power:
 	phy_exit(dwc2->phy);
+clk_disable:
+	clk_disable(dwc2->clk);
+clk_put:
+	clk_put(dwc2->clk);
 release_region:
 	release_region(iores);
 
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/5] usb: dwc2: add reset controller dependency for probe via oftree
  2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 2/5] usb: dwc2: add clk dependency for probe via oftree Michael Grzeschik
@ 2020-12-16 20:45 ` Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 4/5] usb: dwc2: update the dr_mode on set_mode callback Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 5/5] usb: dwc2: add support to force gadget mode Michael Grzeschik
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

The dwc2 controller is connected to one reset controller which needs to be
triggered before it is able to operate. This patch adds the referenced reset
controller in the devicetree to be used.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/usb/dwc2/dwc2.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
index 13455479ef..6f5127fc3b 100644
--- a/drivers/usb/dwc2/dwc2.c
+++ b/drivers/usb/dwc2/dwc2.c
@@ -12,6 +12,7 @@
 #include <errno.h>
 #include <driver.h>
 #include <linux/clk.h>
+#include <linux/reset.h>
 
 #include "dwc2.h"
 
@@ -61,6 +62,10 @@ static int dwc2_probe(struct device_d *dev)
 	if (ret)
 		goto clk_put;
 
+	ret = device_reset_us(dev, 2);
+	if (ret)
+		goto clk_disable;
+
 	dwc2->phy = phy_optional_get(dev, "usb2-phy");
 	if (IS_ERR(dwc2->phy)) {
 		ret = PTR_ERR(dwc2->phy);
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 4/5] usb: dwc2: update the dr_mode on set_mode callback
  2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
                   ` (2 preceding siblings ...)
  2020-12-16 20:45 ` [PATCH 3/5] usb: dwc2: add reset controller " Michael Grzeschik
@ 2020-12-16 20:45 ` Michael Grzeschik
  2020-12-16 20:45 ` [PATCH 5/5] usb: dwc2: add support to force gadget mode Michael Grzeschik
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

The dwc2 dr_mode can be configured with otg.mode in otg mode. Currently
the mode will not be set with the users decision. This patch fixes this
by overwriting the mode with the one set by set_mode callback.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/usb/dwc2/dwc2.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
index 6f5127fc3b..65b92b542e 100644
--- a/drivers/usb/dwc2/dwc2.c
+++ b/drivers/usb/dwc2/dwc2.c
@@ -20,6 +20,9 @@ static int dwc2_set_mode(void *ctx, enum usb_dr_mode mode)
 {
 	struct dwc2 *dwc2 = ctx;
 	int ret = -ENODEV;
+	int oldmode = dwc2->dr_mode;
+
+	dwc2->dr_mode = mode;
 
 	if (mode == USB_DR_MODE_HOST || mode == USB_DR_MODE_OTG) {
 		if (IS_ENABLED(CONFIG_USB_DWC2_HOST))
@@ -34,6 +37,9 @@ static int dwc2_set_mode(void *ctx, enum usb_dr_mode mode)
 			dwc2_err(dwc2, "Peripheral support not available\n");
 	}
 
+	if (ret)
+		dwc2->dr_mode = oldmode;
+
 	return ret;
 }
 
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 5/5] usb: dwc2: add support to force gadget mode
  2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
                   ` (3 preceding siblings ...)
  2020-12-16 20:45 ` [PATCH 4/5] usb: dwc2: update the dr_mode on set_mode callback Michael Grzeschik
@ 2020-12-16 20:45 ` Michael Grzeschik
  4 siblings, 0 replies; 7+ messages in thread
From: Michael Grzeschik @ 2020-12-16 20:45 UTC (permalink / raw)
  To: barebox

In case the driver is to be run in peripheral mode rather than otg, it
needs to be forced in hardware to the selected mode. This patch adds
support to set and clear that hardware override. The functions are
mostly copied from linux.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
---
 drivers/usb/dwc2/gadget.c | 144 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index aa7447c9b4..b8ec37be78 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 #include <dma.h>
 #include <usb/gadget.h>
+#include <linux/iopoll.h>
 #include "dwc2.h"
 
 #define to_dwc2 gadget_to_dwc2
@@ -2660,6 +2661,144 @@ static int dwc2_eps_alloc(struct dwc2 *dwc2)
 	return 0;
 }
 
+/**
+ * dwc2_wait_for_mode() - Waits for the controller mode.
+ * @dwc2:	Programming view of the DWC_otg controller.
+ * @host_mode:	If true, waits for host mode, otherwise device mode.
+ */
+static void dwc2_wait_for_mode(struct dwc2 *dwc2, bool host_mode)
+{
+	int val, ret;
+
+	dev_vdbg(dwc2->dev, "Waiting for %s mode\n",
+		 host_mode ? "host" : "device");
+
+	ret = readx_poll_timeout(dwc2_is_host_mode, dwc2, val,
+			val == host_mode, 110 * USEC_PER_MSEC);
+	if (ret)
+		dev_err(dwc2->dev, "%s: Couldn't set %s mode\n",
+				 __func__, host_mode ? "host" : "device");
+
+	dev_vdbg(dwc2->dev, "%s mode set\n",
+		 host_mode ? "Host" : "Device");
+}
+
+/**
+ * dwc2_iddig_filter_enabled() - Returns true if the IDDIG debounce
+ * filter is enabled.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static bool dwc2_iddig_filter_enabled(struct dwc2 *dwc2)
+{
+	u32 gsnpsid;
+	u32 ghwcfg4;
+
+	/* Check if core configuration includes the IDDIG filter. */
+	ghwcfg4 = dwc2_readl(dwc2, GHWCFG4);
+	if (!(ghwcfg4 & GHWCFG4_IDDIG_FILT_EN))
+		return false;
+
+	/*
+	 * Check if the IDDIG debounce filter is bypassed. Available
+	 * in core version >= 3.10a.
+	 */
+	gsnpsid = dwc2_readl(dwc2, GSNPSID);
+	if (gsnpsid >= DWC2_CORE_REV_3_10a) {
+		u32 gotgctl = dwc2_readl(dwc2, GOTGCTL);
+
+		if (gotgctl & GOTGCTL_DBNCE_FLTR_BYPASS)
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * dwc2_force_mode() - Force the mode of the controller.
+ *
+ * Forcing the mode is needed for two cases:
+ *
+ * 1) If the dr_mode is set to either HOST or PERIPHERAL we force the
+ * controller to stay in a particular mode regardless of ID pin
+ * changes. We do this once during probe.
+ *
+ * 2) During probe we want to read reset values of the hw
+ * configuration registers that are only available in either host or
+ * device mode. We may need to force the mode if the current mode does
+ * not allow us to access the register in the mode that we want.
+ *
+ * In either case it only makes sense to force the mode if the
+ * controller hardware is OTG capable.
+ *
+ * Checks are done in this function to determine whether doing a force
+ * would be valid or not.
+ *
+ * If a force is done, it requires a IDDIG debounce filter delay if
+ * the filter is configured and enabled. We poll the current mode of
+ * the controller to account for this delay.
+ *
+ * @dwc2: Programming view of DWC_otg controller
+ * @host: Host mode flag
+ */
+static void dwc2_force_mode(struct dwc2 *dwc2, bool host)
+{
+	u32 gusbcfg;
+	u32 set;
+	u32 clear;
+
+	dev_dbg(dwc2->dev, "Forcing mode to %s\n", host ? "host" : "device");
+
+	/*
+	 * If dr_mode is either peripheral or host only, there is no
+	 * need to ever force the mode to the opposite mode.
+	 */
+	if (WARN_ON(host && dwc2->dr_mode == USB_DR_MODE_PERIPHERAL))
+		return;
+
+	if (WARN_ON(!host && dwc2->dr_mode == USB_DR_MODE_HOST))
+		return;
+
+	gusbcfg = dwc2_readl(dwc2, GUSBCFG);
+
+	set = host ? GUSBCFG_FORCEHOSTMODE : GUSBCFG_FORCEDEVMODE;
+	clear = host ? GUSBCFG_FORCEDEVMODE : GUSBCFG_FORCEHOSTMODE;
+
+	gusbcfg &= ~clear;
+	gusbcfg |= set;
+	dwc2_writel(dwc2, gusbcfg, GUSBCFG);
+
+	dwc2_wait_for_mode(dwc2, host);
+
+	return;
+}
+
+/**
+ * dwc2_clear_force_mode() - Clears the force mode bits.
+ *
+ * After clearing the bits, wait up to 100 ms to account for any
+ * potential IDDIG filter delay. We can't know if we expect this delay
+ * or not because the value of the connector ID status is affected by
+ * the force mode. We only need to call this once during probe if
+ * dr_mode == OTG.
+ *
+ * @dwc2: Programming view of DWC_otg controller
+ */
+static void dwc2_clear_force_mode(struct dwc2 *dwc2)
+{
+	u32 gusbcfg;
+
+	dev_dbg(dwc2->dev, "Clearing force mode bits\n");
+
+	gusbcfg = dwc2_readl(dwc2, GUSBCFG);
+	gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
+	gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
+	dwc2_writel(dwc2, gusbcfg, GUSBCFG);
+
+	if (dwc2_iddig_filter_enabled(dwc2))
+		mdelay(100);
+}
+
 int dwc2_gadget_init(struct dwc2 *dwc2)
 {
 	u32 dctl;
@@ -2684,6 +2823,11 @@ int dwc2_gadget_init(struct dwc2 *dwc2)
 
 	dwc2->gadget.is_otg = (dwc2->dr_mode == USB_DR_MODE_OTG) ? 1 : 0;
 
+	if (dwc2->gadget.is_otg)
+		dwc2_clear_force_mode(dwc2);
+	else
+		dwc2_force_mode(dwc2, false);
+
 	ret = dwc2_eps_alloc(dwc2);
 	if (ret) {
 		dwc2_err(dwc2, "Endpoints allocation failed: %d\n", ret);
-- 
2.29.2


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing
  2020-12-16 20:45 ` [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing Michael Grzeschik
@ 2020-12-17 11:00   ` Jules Maselbas
  0 siblings, 0 replies; 7+ messages in thread
From: Jules Maselbas @ 2020-12-17 11:00 UTC (permalink / raw)
  To: Michael Grzeschik; +Cc: barebox

Hi Micheal,

I am testing your patches, but this one doesn't compile.

On Wed, Dec 16, 2020 at 09:45:30PM +0100, Michael Grzeschik wrote:
> The driver needs to cleanup the resources if an error occurred. Otherwise,
> on deferred probing, it will fail to take the resources for a second time.
> 
> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
> ---
>  drivers/usb/dwc2/dwc2.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/usb/dwc2/dwc2.c b/drivers/usb/dwc2/dwc2.c
> index bd33334a83..87d0ec7a5a 100644
> --- a/drivers/usb/dwc2/dwc2.c
> +++ b/drivers/usb/dwc2/dwc2.c
> @@ -53,7 +53,7 @@ static int dwc2_probe(struct device_d *dev)
>  	dwc2->phy = phy_optional_get(dev, "usb2-phy");
>  	if (IS_ERR(dwc2->phy)) {
>  		ret = PTR_ERR(dwc2->phy);
> -		return ret;
> +		goto release_region;
>  	}
>  
>  	ret = phy_init(dwc2->phy);
> @@ -100,7 +100,8 @@ error:
>  	phy_power_off(dwc2->phy);
>  err_phy_power:
>  	phy_exit(dwc2->phy);
> -err_phy_init:
> +release_region:
> +	release_region(iores);
error: label ‘err_phy_init’ used but not defined
in drivers/usb/dwc2.c:61
        ret = phy_init(dwc2->phy);
        if (ret)
                goto err_phy_init;


Jules


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-12-17 11:00 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-16 20:45 [PATCH 0/5] dwc2: improve gadget support Michael Grzeschik
2020-12-16 20:45 ` [PATCH 1/5] usb: dwc2: cleanup on error for deferred probing Michael Grzeschik
2020-12-17 11:00   ` Jules Maselbas
2020-12-16 20:45 ` [PATCH 2/5] usb: dwc2: add clk dependency for probe via oftree Michael Grzeschik
2020-12-16 20:45 ` [PATCH 3/5] usb: dwc2: add reset controller " Michael Grzeschik
2020-12-16 20:45 ` [PATCH 4/5] usb: dwc2: update the dr_mode on set_mode callback Michael Grzeschik
2020-12-16 20:45 ` [PATCH 5/5] usb: dwc2: add support to force gadget mode Michael Grzeschik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox