From: manish.narani@xilinx.com (Manish Narani)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH] usb: dwc3: gadget: add support for OTG in gadget framework
Date: Wed, 4 Jan 2017 18:52:58 +0530 [thread overview]
Message-ID: <1483536181-22356-4-git-send-email-mnarani@xilinx.com> (raw)
In-Reply-To: <1483536181-22356-1-git-send-email-mnarani@xilinx.com>
This patch adds support for OTG in DWC3 gadget framework. This
also adds support for HNP polling by host while in OTG mode.
Modifications in couple of functions to make it in sync with
OTG driver while keeping its original functionality intact.
Signed-off-by: Manish Narani <mnarani@xilinx.com>
---
drivers/usb/dwc3/ep0.c | 49 +++++++++++++++++++++++---
drivers/usb/dwc3/gadget.c | 87 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 116 insertions(+), 20 deletions(-)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 4878d18..aa78c1b 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -334,6 +334,8 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
usb_status |= 1 << USB_DEV_STAT_U2_ENABLED;
}
+ usb_status |= dwc->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP;
+
break;
case USB_RECIP_INTERFACE:
@@ -448,11 +450,45 @@ static int dwc3_ep0_handle_device(struct dwc3 *dwc,
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
+ if (set)
+ dwc->remote_wakeup = 1;
+ else
+ dwc->remote_wakeup = 0;
break;
- /*
- * 9.4.1 says only only for SS, in AddressState only for
- * default control pipe
- */
+ case USB_DEVICE_B_HNP_ENABLE:
+ dev_dbg(dwc->dev,
+ "SET_FEATURE: USB_DEVICE_B_HNP_ENABLE\n");
+ if (set && dwc->gadget.is_otg) {
+ if (dwc->gadget.host_request_flag) {
+ struct usb_phy *phy =
+ usb_get_phy(USB_PHY_TYPE_USB3);
+
+ dwc->gadget.b_hnp_enable = 0;
+ dwc->gadget.host_request_flag = 0;
+ otg_start_hnp(phy->otg);
+ usb_put_phy(phy);
+ } else {
+ dwc->gadget.b_hnp_enable = 1;
+ }
+ } else
+ return -EINVAL;
+ break;
+
+ case USB_DEVICE_A_HNP_SUPPORT:
+ /* RH port supports HNP */
+ dev_dbg(dwc->dev,
+ "SET_FEATURE: USB_DEVICE_A_HNP_SUPPORT\n");
+ break;
+
+ case USB_DEVICE_A_ALT_HNP_SUPPORT:
+ /* other RH port does */
+ dev_dbg(dwc->dev,
+ "SET_FEATURE: USB_DEVICE_A_ALT_HNP_SUPPORT\n");
+ break;
+ /*
+ * 9.4.1 says only only for SS, in AddressState only for
+ * default control pipe
+ */
case USB_DEVICE_U1_ENABLE:
ret = dwc3_ep0_handle_u1(dwc, state, set);
break;
@@ -759,7 +795,10 @@ static int dwc3_ep0_std_request(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
switch (ctrl->bRequest) {
case USB_REQ_GET_STATUS:
- ret = dwc3_ep0_handle_status(dwc, ctrl);
+ if (le16_to_cpu(ctrl->wIndex) == OTG_STS_SELECTOR)
+ ret = dwc3_ep0_delegate_req(dwc, ctrl);
+ else
+ ret = dwc3_ep0_handle_status(dwc, ctrl);
break;
case USB_REQ_CLEAR_FEATURE:
ret = dwc3_ep0_handle_feature(dwc, ctrl, 0);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 6785595..3b0b771 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -34,6 +34,7 @@
#include "core.h"
#include "gadget.h"
#include "io.h"
+#include "otg.h"
/**
* dwc3_gadget_set_test_mode - Enables USB2 Test Modes
@@ -1792,25 +1793,51 @@ static int dwc3_gadget_start(struct usb_gadget *g,
int ret = 0;
int irq;
- irq = dwc->irq_gadget;
- ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
- IRQF_SHARED, "dwc3", dwc->ev_buf);
- if (ret) {
- dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
- irq, ret);
- goto err0;
- }
-
spin_lock_irqsave(&dwc->lock, flags);
if (dwc->gadget_driver) {
dev_err(dwc->dev, "%s is already bound to %s\n",
dwc->gadget.name,
dwc->gadget_driver->driver.name);
ret = -EBUSY;
- goto err1;
+ goto err0;
}
- dwc->gadget_driver = driver;
+ if (g->is_otg) {
+ static struct usb_gadget_driver *prev_driver;
+ /* There are two instances where OTG functionality is enabled :
+ * 1. This function will be called from OTG driver to start the
+ * gadget
+ * 2. This function will be called by the Linux Class Driver to
+ * start the gadget
+ * Below code will keep synchronization between these calls. The
+ * "driver" argument will be NULL when it is called from the OTG
+ * driver, so we are maintaning a global variable "prev_driver"
+ * to assign value of argument "driver" (from class driver) to
+ * dwc->gadget_driver when it is called from OTG.
+ */
+ if (driver) {
+ prev_driver = driver;
+ if (dwc->otg) {
+ struct dwc3_otg *otg = dwc->otg;
+
+ if ((otg->host_started ||
+ (!otg->peripheral_started)))
+ goto err0;
+ }
+ dwc->gadget_driver = driver;
+ } else
+ dwc->gadget_driver = prev_driver;
+ } else
+ dwc->gadget_driver = driver;
+
+ irq = dwc->irq_gadget;
+ ret = request_threaded_irq(irq, dwc3_interrupt, dwc3_thread_interrupt,
+ IRQF_SHARED, "dwc3", dwc->ev_buf);
+ if (ret) {
+ dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+ irq, ret);
+ goto err0;
+ }
if (pm_runtime_active(dwc->dev))
__dwc3_gadget_start(dwc);
@@ -1819,11 +1846,9 @@ static int dwc3_gadget_start(struct usb_gadget *g,
return 0;
-err1:
- spin_unlock_irqrestore(&dwc->lock, flags);
- free_irq(irq, dwc);
-
err0:
+ dwc->gadget_driver = NULL;
+ spin_unlock_irqrestore(&dwc->lock, flags);
return ret;
}
@@ -2977,6 +3002,18 @@ int dwc3_gadget_init(struct dwc3 *dwc)
dwc->irq_gadget = irq;
+ if (dwc->dr_mode == USB_DR_MODE_OTG) {
+ struct usb_phy *phy;
+ /* Switch otg to peripheral mode */
+ phy = usb_get_phy(USB_PHY_TYPE_USB3);
+ if (!IS_ERR(phy)) {
+ if (phy && phy->otg)
+ otg_set_peripheral(phy->otg,
+ (struct usb_gadget *)(long)1);
+ usb_put_phy(phy);
+ }
+ }
+
dwc->ctrl_req = dma_alloc_coherent(dwc->sysdev, sizeof(*dwc->ctrl_req),
&dwc->ctrl_req_addr, GFP_KERNEL);
if (!dwc->ctrl_req) {
@@ -3066,6 +3103,26 @@ int dwc3_gadget_init(struct dwc3 *dwc)
goto err5;
}
+ if (dwc->dr_mode == USB_DR_MODE_OTG) {
+ struct usb_phy *phy;
+
+ phy = usb_get_phy(USB_PHY_TYPE_USB3);
+ if (!IS_ERR(phy)) {
+ if (phy && phy->otg) {
+ ret = otg_set_peripheral(phy->otg,
+ &dwc->gadget);
+ if (ret) {
+ usb_put_phy(phy);
+ phy = NULL;
+ goto err5;
+ }
+ } else {
+ usb_put_phy(phy);
+ phy = NULL;
+ }
+ }
+ }
+
return 0;
err5:
--
2.1.1
next prev parent reply other threads:[~2017-01-04 13:22 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-04 13:22 [RFC PATCH] arch: arm64: dts: add USB OTG interrupts support in ZynqMP device tree Manish Narani
2017-01-04 13:22 ` [RFC PATCH] usb: dwc3: add support for OTG driver compilation Manish Narani
2017-01-04 13:31 ` Felipe Balbi
2017-01-05 5:27 ` Manish Narani
2017-01-05 9:20 ` Felipe Balbi
2017-01-04 13:22 ` [RFC PATCH] usb: dwc3: core: add OTG support function calls and modifications Manish Narani
2017-01-04 13:22 ` Manish Narani [this message]
2017-01-04 14:03 ` [RFC PATCH] usb: dwc3: gadget: add support for OTG in gadget framework Felipe Balbi
2017-01-04 13:22 ` [RFC PATCH] usb: dwc3: host: add support for OTG in DWC3 host driver Manish Narani
2017-01-04 13:32 ` Felipe Balbi
2017-01-05 12:24 ` Manish Narani
2017-01-04 13:23 ` [RFC PATCH] usb: dwc3: otg: Adding OTG driver for DWC3 controller Manish Narani
2017-01-04 13:23 ` [RFC PATCH] usb: host: xhci: plat: add support for otg_set_host() call Manish Narani
2017-01-04 13:30 ` [RFC PATCH] arch: arm64: dts: add USB OTG interrupts support in ZynqMP device tree Felipe Balbi
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=1483536181-22356-4-git-send-email-mnarani@xilinx.com \
--to=manish.narani@xilinx.com \
--cc=linux-arm-kernel@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).