linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v7 0/4] usb: dwc3: dual-role support
@ 2016-06-10 13:17 Roger Quadros
  2016-06-10 13:17 ` [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions Roger Quadros
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:17 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

Hi,

This series adds dual role support to dwc3 controller driver.
Series depends on the OTG/dual-role framework [1].

[1] - http://thread.gmane.org/gmane.linux.usb.general/143568

Patches are based on Felipe's balbi/usb.git testing/next

Changelog:

v7:
- rebased to v4.7-rc1 + balbi/usb.git testing/next
- cleaned up otg irq resource code

v6:
- use just otg irq to get otg events and don't depend on extcon at all.
- follow OTG flow in TRM strictly.
- use tracepoints instead of dev_dbg().
- match IRQ flags in dwc3_omap and core.c for shared otg interrupt.

v5: Internal revision. Not sent to mailing list.

v4: first version that was reviewed.

cheers,
-roger


Roger Quadros (4):
  usb: dwc3: core.h: add some register definitions
  usb: dwc3: add dual-role support
  ARM: dts: dra7*-evm: Enable dual-role for usb1
  ARM: dts: am43xx: Enable dual-role on USB1

 arch/arm/boot/dts/am437x-gp-evm.dts     |   5 +-
 arch/arm/boot/dts/am437x-sk-evm.dts     |   5 +-
 arch/arm/boot/dts/am43x-epos-evm.dts    |   5 +-
 arch/arm/boot/dts/dra7-evm.dts          |   5 +-
 arch/arm/boot/dts/dra72-evm-common.dtsi |   5 +-
 drivers/usb/dwc3/core.c                 | 546 +++++++++++++++++++++++++++++++-
 drivers/usb/dwc3/core.h                 | 114 ++++++-
 drivers/usb/dwc3/gadget.c               |   6 +-
 drivers/usb/dwc3/host.c                 |   2 +
 9 files changed, 677 insertions(+), 16 deletions(-)

-- 
2.7.4

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

* [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions
  2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
@ 2016-06-10 13:17 ` Roger Quadros
  2016-06-20  9:28   ` Felipe Balbi
  2016-06-10 13:17 ` [PATCH v7 2/4] usb: dwc3: add dual-role support Roger Quadros
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:17 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

Add OTG and GHWPARAMS6 register definitions

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/usb/dwc3/core.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 8fb6361..32bb7531 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -197,6 +197,15 @@
 #define DWC3_GCTL_GBLHIBERNATIONEN	(1 << 1)
 #define DWC3_GCTL_DSBLCLKGTNG		(1 << 0)
 
+/* Global Status Register */
+#define DWC3_GSTS_OTG_IP	BIT(10)
+#define DWC3_GSTS_BC_IP		BIT(9)
+#define DWC3_GSTS_ADP_IP	BIT(8)
+#define DWC3_GSTS_HOST_IP	BIT(7)
+#define DWC3_GSTS_DEVICE_IP	BIT(6)
+#define DWC3_GSTS_CSR_TIMEOUT	BIT(5)
+#define DWC3_GSTS_BUS_ERR_ADDR_VLD	BIT(4)
+
 /* Global USB2 PHY Configuration Register */
 #define DWC3_GUSB2PHYCFG_PHYSOFTRST	(1 << 31)
 #define DWC3_GUSB2PHYCFG_SUSPHY		(1 << 6)
@@ -269,7 +278,12 @@
 #define DWC3_MAX_HIBER_SCRATCHBUFS		15
 
 /* Global HWPARAMS6 Register */
-#define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
+#define DWC3_GHWPARAMS6_BCSUPPORT		BIT(14)
+#define DWC3_GHWPARAMS6_OTG3SUPPORT		BIT(13)
+#define DWC3_GHWPARAMS6_ADPSUPPORT		BIT(12)
+#define DWC3_GHWPARAMS6_HNPSUPPORT		BIT(11)
+#define DWC3_GHWPARAMS6_SRPSUPPORT		BIT(10)
+#define DWC3_GHWPARAMS6_EN_FPGA			BIT(7)
 
 /* Global HWPARAMS7 Register */
 #define DWC3_GHWPARAMS7_RAM1_DEPTH(n)	((n) & 0xffff)
@@ -441,6 +455,74 @@
 #define DWC3_DEPCMD_TYPE_BULK		2
 #define DWC3_DEPCMD_TYPE_INTR		3
 
+/* OTG Configuration Register */
+#define DWC3_OCFG_DISPWRCUTTOFF		BIT(5)
+#define DWC3_OCFG_HIBDISMASK		BIT(4)
+#define DWC3_OCFG_SFTRSTMASK		BIT(3)
+#define DWC3_OCFG_OTGVERSION		BIT(2)
+#define DWC3_OCFG_HNPCAP		BIT(1)
+#define DWC3_OCFG_SRPCAP		BIT(0)
+
+/* OTG CTL Register */
+#define DWC3_OCTL_OTG3GOERR		BIT(7)
+#define DWC3_OCTL_PERIMODE		BIT(6)
+#define DWC3_OCTL_PRTPWRCTL		BIT(5)
+#define DWC3_OCTL_HNPREQ		BIT(4)
+#define DWC3_OCTL_SESREQ		BIT(3)
+#define DWC3_OCTL_TERMSELIDPULSE	BIT(2)
+#define DWC3_OCTL_DEVSETHNPEN		BIT(1)
+#define DWC3_OCTL_HSTSETHNPEN		BIT(0)
+
+/* OTG Event Register */
+#define DWC3_OEVT_DEVICEMODE		BIT(31)
+#define DWC3_OEVT_XHCIRUNSTPSET		BIT(27)
+#define DWC3_OEVT_DEVRUNSTPSET		BIT(26)
+#define DWC3_OEVT_HIBENTRY		BIT(25)
+#define DWC3_OEVT_CONIDSTSCHNG		BIT(24)
+#define DWC3_OEVT_HRRCONFNOTIF		BIT(23)
+#define DWC3_OEVT_HRRINITNOTIF		BIT(22)
+#define DWC3_OEVT_ADEVIDLE		BIT(21)
+#define DWC3_OEVT_ADEVBHOSTEND		BIT(20)
+#define DWC3_OEVT_ADEVHOST		BIT(19)
+#define DWC3_OEVT_ADEVHNPCHNG		BIT(18)
+#define DWC3_OEVT_ADEVSRPDET		BIT(17)
+#define DWC3_OEVT_ADEVSESSENDDET	BIT(16)
+#define DWC3_OEVT_BDEVBHOSTEND		BIT(11)
+#define DWC3_OEVT_BDEVHNPCHNG		BIT(10)
+#define DWC3_OEVT_BDEVSESSVLDDET	BIT(9)
+#define DWC3_OEVT_BDEVVBUSCHNG		BIT(8)
+#define DWC3_OEVT_BSESSVLD		BIT(3)
+#define DWC3_OEVT_HSTNEGSTS		BIT(2)
+#define DWC3_OEVT_SESREQSTS		BIT(1)
+#define DWC3_OEVT_ERROR			BIT(0)
+
+/* OTG Event Enable Register */
+#define DWC3_OEVTEN_XHCIRUNSTPSETEN	BIT(27)
+#define DWC3_OEVTEN_DEVRUNSTPSETEN	BIT(26)
+#define DWC3_OEVTEN_HIBENTRYEN		BIT(25)
+#define DWC3_OEVTEN_CONIDSTSCHNGEN	BIT(24)
+#define DWC3_OEVTEN_HRRCONFNOTIFEN	BIT(23)
+#define DWC3_OEVTEN_HRRINITNOTIFEN	BIT(22)
+#define DWC3_OEVTEN_ADEVIDLEEN		BIT(21)
+#define DWC3_OEVTEN_ADEVBHOSTENDEN	BIT(20)
+#define DWC3_OEVTEN_ADEVHOSTEN		BIT(19)
+#define DWC3_OEVTEN_ADEVHNPCHNGEN	BIT(18)
+#define DWC3_OEVTEN_ADEVSRPDETEN	BIT(17)
+#define DWC3_OEVTEN_ADEVSESSENDDETEN	BIT(16)
+#define DWC3_OEVTEN_BDEVHOSTENDEN	BIT(11)
+#define DWC3_OEVTEN_BDEVHNPCHNGEN	BIT(10)
+#define DWC3_OEVTEN_BDEVSESSVLDDETEN	BIT(9)
+#define DWC3_OEVTEN_BDEVVBUSCHNGE	BIT(8)
+
+/* OTG Status Register */
+#define DWC3_OSTS_DEVRUNSTP		BIT(13)
+#define DWC3_OSTS_XHCIRUNSTP		BIT(12)
+#define DWC3_OSTS_PERIPHERALSTATE	BIT(4)
+#define DWC3_OSTS_XHCIPRTPOWER		BIT(3)
+#define DWC3_OSTS_BSESVLD		BIT(2)
+#define DWC3_OSTS_VBUSVLD		BIT(1)
+#define DWC3_OSTS_CONIDSTS		BIT(0)
+
 /* Structures */
 
 struct dwc3_trb;
-- 
2.7.4

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

* [PATCH v7 2/4] usb: dwc3: add dual-role support
  2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
  2016-06-10 13:17 ` [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions Roger Quadros
@ 2016-06-10 13:17 ` Roger Quadros
  2016-06-12  9:11   ` Peter Chen
  2016-06-10 13:17 ` [PATCH v7 3/4] ARM: dts: dra7*-evm: Enable dual-role for usb1 Roger Quadros
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:17 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

Register with the USB OTG/DRD core. Since we don't support
OTG yet we just work as a dual-role device even
if device tree says "otg".

Get ID and VBUS information from the OTG controller
and kick the OTG state machine.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 drivers/usb/dwc3/core.c   | 546 +++++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/dwc3/core.h   |  30 ++-
 drivers/usb/dwc3/gadget.c |   6 +-
 drivers/usb/dwc3/host.c   |   2 +
 4 files changed, 574 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index d51c9a9..28d2da2 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -56,6 +56,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
 	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
 	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
 	reg |= DWC3_GCTL_PRTCAPDIR(mode);
+	dwc->current_mode = mode;
 	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
 }
 
@@ -756,6 +757,448 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
 	return 0;
 }
 
+/* Get OTG events and sync it to OTG fsm */
+static void dwc3_otg_fsm_sync(struct dwc3 *dwc)
+{
+	u32 reg;
+	int id, vbus;
+
+	/*
+	 * calling usb_otg_sync_inputs() during resume breaks host
+	 * if adapter was removed during suspend as xhci driver
+	 * is not prepared to see hcd removal before xhci_resume.
+	 */
+	if (dwc->otg_prevent_sync)
+		return;
+
+	reg = dwc3_readl(dwc->regs, DWC3_OSTS);
+	dwc3_trace(trace_dwc3_core, "otgstatus 0x%x\n", reg);
+
+	id = !!(reg & DWC3_OSTS_CONIDSTS);
+	vbus = !!(reg & DWC3_OSTS_BSESVLD);
+
+	dwc3_trace(trace_dwc3_core, "id %d vbus %d\n", id, vbus);
+	dwc->otg->fsm.id = id;
+	dwc->otg->fsm.b_sess_vld = vbus;
+	usb_otg_sync_inputs(dwc->otg);
+}
+
+static void dwc3_otg_mask_irq(struct dwc3 *dwc)
+{
+	dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
+	dwc3_writel(dwc->regs, DWC3_OEVTEN, 0);
+}
+
+static void dwc3_otg_unmask_irq(struct dwc3 *dwc)
+{
+	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
+}
+
+static void dwc3_otg_disable_events(struct dwc3 *dwc, u32 disable_mask)
+{
+	dwc->oevten &= ~(disable_mask);
+	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
+}
+
+static void dwc3_otg_enable_events(struct dwc3 *dwc, u32 enable_mask)
+{
+	dwc->oevten |= (enable_mask);
+	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
+}
+
+#define DWC3_OTG_ALL_EVENTS	(DWC3_OEVTEN_XHCIRUNSTPSETEN | \
+		DWC3_OEVTEN_DEVRUNSTPSETEN | DWC3_OEVTEN_HIBENTRYEN | \
+		DWC3_OEVTEN_CONIDSTSCHNGEN | DWC3_OEVTEN_HRRCONFNOTIFEN | \
+		DWC3_OEVTEN_HRRINITNOTIFEN | DWC3_OEVTEN_ADEVIDLEEN | \
+		DWC3_OEVTEN_ADEVBHOSTENDEN | DWC3_OEVTEN_ADEVHOSTEN | \
+		DWC3_OEVTEN_ADEVHNPCHNGEN | DWC3_OEVTEN_ADEVSRPDETEN | \
+		DWC3_OEVTEN_ADEVSESSENDDETEN | DWC3_OEVTEN_BDEVHOSTENDEN | \
+		DWC3_OEVTEN_BDEVHNPCHNGEN | DWC3_OEVTEN_BDEVSESSVLDDETEN | \
+		DWC3_OEVTEN_BDEVVBUSCHNGE)
+
+static int dwc3_drd_start_host(struct usb_otg *otg, int on);
+static int dwc3_drd_start_gadget(struct usb_otg *otg, int on);
+static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	/*
+	 * this bit is needed for otg-host to work after system suspend/resume
+	 */
+	if ((dwc->otg->state == OTG_STATE_A_HOST) &&
+	    !(dwc->oevt & DWC3_OEVT_DEVICEMODE)) {
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		dwc3_drd_start_host(dwc->otg, true);
+		spin_lock_irqsave(&dwc->lock, flags);
+	}
+
+	dwc3_otg_fsm_sync(dwc);
+	dwc3_otg_unmask_irq(dwc);
+
+	dwc->oevt = 0;
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t dwc3_otg_irq(int irq, void *_dwc)
+{
+	struct dwc3 *dwc = _dwc;
+	irqreturn_t ret = IRQ_NONE;
+	u32 reg;
+
+	reg = dwc3_readl(dwc->regs, DWC3_OEVT);
+	if (reg) {
+		dwc->oevt = reg;
+		dwc3_writel(dwc->regs, DWC3_OEVT, reg);
+		dwc3_otg_mask_irq(dwc);
+		ret = IRQ_WAKE_THREAD;
+	}
+
+	return ret;
+}
+
+/* --------------------- Dual-Role management ------------------------------- */
+static void dwc3_otgregs_init(struct dwc3 *dwc)
+{
+	u32 reg;
+
+	/*
+	 * Prevent host/device reset from resetting OTG core.
+	 * If we don't do this then xhci_reset (USBCMD.HCRST) will reset
+	 * the signal outputs sent to the PHY, the OTG FSM logic of the
+	 * core and also the resets to the VBUS filters inside the core.
+	 */
+	reg = dwc3_readl(dwc->regs, DWC3_OCFG);
+	reg |= DWC3_OCFG_SFTRSTMASK;
+	dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+
+	/* Disable hibernation for simplicity */
+	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+	reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
+	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+	/*
+	 * Initialize OTG registers as per
+	 * Figure 11-4 OTG Driver Overall Programming Flow
+	 */
+	/* OCFG.SRPCap = 0, OCFG.HNPCap = 0 */
+	reg = dwc3_readl(dwc->regs, DWC3_OCFG);
+	reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
+	dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+	/* OEVT = FFFF */
+	dwc3_writel(dwc->regs, DWC3_OEVT, ~0);
+	/* OEVTEN = 0 */
+	dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
+	/* OEVTEN.ConIDStsChngEn = 1. Instead we enable all events */
+	dwc3_otg_enable_events(dwc, DWC3_OTG_ALL_EVENTS);
+	/*
+	 * OCTL.PeriMode = 1, OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0,
+	 * OCTL.HNPReq = 0
+	 */
+	reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+	reg |= DWC3_OCTL_PERIMODE;
+	reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN |
+		 DWC3_OCTL_HNPREQ);
+	dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+}
+
+static int dwc3_drd_start_host(struct usb_otg *otg, int on)
+{
+	struct dwc3 *dwc = dev_get_drvdata(otg->dev);
+	u32 reg;
+	unsigned long flags;
+
+	dwc3_trace(trace_dwc3_core, "%s: %d\n", __func__, on);
+
+	/* switch OTG core */
+	if (on) {
+		/* As per Figure 11-10 A-Device Flow Diagram */
+
+		spin_lock_irqsave(&dwc->lock, flags);
+		/* OCFG.HNPCap = 0, OCFG.SRPCap = 0 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
+		reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
+		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+
+		/*
+		 * OCTL.PeriMode=0, OCTL.TermSelDLPulse = 0,
+		 * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
+		 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+		reg &= ~(DWC3_OCTL_PERIMODE | DWC3_OCTL_TERMSELIDPULSE |
+			 DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
+		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+
+		/*
+		 * OCFG.DisPrtPwrCutoff = 0/1
+		 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
+		reg &= ~DWC3_OCFG_DISPWRCUTTOFF;
+		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+
+		/* start the xHCI host driver */
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		usb_otg_start_host(otg, true);
+		spin_lock_irqsave(&dwc->lock, flags);
+
+		/*
+		 * OCFG.SRPCap = 1, OCFG.HNPCap = GHWPARAMS6.HNP_CAP
+		 * We don't want SRP/HNP for simple dual-role so leave
+		 * these disabled.
+		 */
+
+		/*
+		 * OEVTEN.OTGADevHostEvntEn = 1
+		 * OEVTEN.OTGADevSessEndDetEvntEn = 1
+		 * We don't want HNP/role-swap so leave these disabled.
+		 */
+
+		/* GUSB2PHYCFG.ULPIAutoRes = 1/0, GUSB2PHYCFG.SusPHY = 1 */
+		if (!dwc->dis_u2_susphy_quirk) {
+			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+			reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+		}
+
+		/* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+		reg |= DWC3_OCTL_PRTPWRCTL;
+		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+	} else {
+		/*
+		 * Exit from A-device flow as per
+		 * Figure 11-4 OTG Driver Overall Programming Flow
+		 */
+		/* stop the HCD */
+		usb_otg_start_host(otg, false);
+
+		spin_lock_irqsave(&dwc->lock, flags);
+		/*
+		 * OEVTEN.OTGADevBHostEndEvntEn=0, OEVTEN.OTGADevHNPChngEvntEn=0
+		 * OEVTEN.OTGADevSessEndDetEvntEn=0,
+		 * OEVTEN.OTGADevHostEvntEn = 0
+		 * But we don't disable any OTG events
+		 */
+
+		/* OCTL.HstSetHNPEn = 0, OCTL.PrtPwrCtl=0 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+		reg &= ~(DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_PRTPWRCTL);
+		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+
+		/* Initialize OTG registers */
+		dwc3_otgregs_init(dwc);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+	}
+
+	return 0;
+}
+
+static int dwc3_drd_start_gadget(struct usb_otg *otg, int on)
+{
+	struct dwc3 *dwc = dev_get_drvdata(otg->dev);
+	u32 reg;
+	unsigned long flags;
+
+	dwc3_trace(trace_dwc3_core, "%s: %d\n", __func__, on);
+	if (on)
+		dwc3_event_buffers_setup(dwc);
+
+	if (on) {
+		/* As per Figure 11-20 B-Device Flow Diagram */
+
+		spin_lock_irqsave(&dwc->lock, flags);
+		/*
+		 * OCFG.HNPCap = GHWPARAMS6.HNP_CAP, OCFG.SRPCap = 1
+		 * but we set them to 0 for simple dual-role operation.
+		 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
+		reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
+		/* OCFG.OTGSftRstMsk = 0/1 */
+		reg |= DWC3_OCFG_SFTRSTMASK;
+		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
+		/*
+		 * OCTL.PeriMode = 1
+		 * OCTL.TermSelDLPulse = 0/1, OCTL.HNPReq = 0
+		 * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
+		 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+		reg |= DWC3_OCTL_PERIMODE;
+		reg &= ~(DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_HNPREQ |
+			 DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
+		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+		/* OEVTEN.OTGBDevSesVldDetEvntEn = 1 */
+		dwc3_otg_enable_events(dwc, DWC3_OEVT_BDEVSESSVLDDET);
+		/* GUSB2PHYCFG.ULPIAutoRes = 0, GUSB2PHYCFG0.SusPHY = 1 */
+		if (!dwc->dis_u2_susphy_quirk) {
+			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+			reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+		}
+		/* GCTL.GblHibernationEn = 0 */
+		reg = dwc3_readl(dwc->regs, DWC3_GCTL);
+		reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
+		dwc3_writel(dwc->regs, DWC3_GCTL, reg);
+
+		spin_unlock_irqrestore(&dwc->lock, flags);
+
+		/* start the Peripheral driver  */
+		usb_otg_start_gadget(otg, true);
+	} else {
+		/*
+		 * Exit from B-device flow as per
+		 * Figure 11-4 OTG Driver Overall Programming Flow
+		 */
+		/* stop the Peripheral driver */
+		usb_otg_start_gadget(otg, false);
+
+		spin_lock_irqsave(&dwc->lock, flags);
+
+		/*
+		 * OEVTEN.OTGBDevHNPChngEvntEn = 0
+		 * OEVTEN.OTGBDevVBusChngEvntEn = 0
+		 * OEVTEN.OTGBDevBHostEndEvntEn = 0
+		 */
+		reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
+		reg &= ~(DWC3_OEVT_BDEVHNPCHNG | DWC3_OEVT_BDEVVBUSCHNG |
+			 DWC3_OEVT_BDEVBHOSTEND);
+		dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
+
+		/* OCTL.DevSetHNPEn = 0, OCTL.HNPReq = 0, OCTL.PeriMode=1 */
+		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
+		reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HNPREQ);
+		reg |= DWC3_OCTL_PERIMODE;
+		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
+
+		/* Initialize OTG registers */
+		dwc3_otgregs_init(dwc);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+	}
+
+	return 0;
+}
+
+static struct otg_fsm_ops dwc3_drd_ops = {
+	.start_host = dwc3_drd_start_host,
+	.start_gadget = dwc3_drd_start_gadget,
+};
+
+static int dwc3_drd_register(struct dwc3 *dwc)
+{
+	int ret;
+
+	/* register parent as DRD device with OTG core */
+	dwc->otg = usb_otg_register(dwc->dev, &dwc->otg_config);
+	if (IS_ERR(dwc->otg)) {
+		ret = PTR_ERR(dwc->otg);
+		if (ret == -ENOTSUPP)
+			dev_err(dwc->dev, "CONFIG_USB_OTG needed for dual-role\n");
+		else
+			dev_err(dwc->dev, "Failed to register with OTG core\n");
+
+		return ret;
+	}
+
+	return 0;
+}
+
+static int dwc3_drd_init(struct dwc3 *dwc)
+{
+	int ret, irq;
+	struct usb_otg_caps *otgcaps = &dwc->otg_caps;
+	u32 reg;
+	unsigned long flags;
+	struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
+
+	irq = platform_get_irq_byname(dwc3_pdev, "otg");
+	if (irq == -EPROBE_DEFER)
+		return irq;
+
+	if (irq <= 0) {
+		irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
+		if (irq == -EPROBE_DEFER)
+			return irq;
+
+		if (irq <= 0) {
+			irq = platform_get_irq(dwc3_pdev, 0);
+			if (irq <= 0) {
+				if (irq != -EPROBE_DEFER)
+					dev_err(dwc->dev, "missing otg IRQ\n");
+
+				if (!irq)
+					irq = -EINVAL;
+				return irq;
+			}
+		}
+	}
+
+	dwc->otg_irq = irq;
+
+	otgcaps->otg_rev = 0;
+	otgcaps->hnp_support = false;
+	otgcaps->srp_support = false;
+	otgcaps->adp_support = false;
+	dwc->otg_config.fsm_ops = &dwc3_drd_ops;
+	dwc->otg_config.otg_caps = otgcaps;
+
+	ret = dwc3_drd_register(dwc);
+	if (ret)
+		return ret;
+
+	/* disable all otg irqs */
+	dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
+	/* clear all events */
+	dwc3_writel(dwc->regs, DWC3_OEVT, ~0);
+
+	ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq,
+				   dwc3_otg_thread_irq,
+				   IRQF_SHARED, "dwc3-otg", dwc);
+	if (ret) {
+		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
+			dwc->otg_irq, ret);
+		ret = -ENODEV;
+		goto error;
+	}
+
+	spin_lock_irqsave(&dwc->lock, flags);
+
+	/*
+	 * As per Figure 11-4 OTG Driver Overall Programming Flow,
+	 * block "Initialize GCTL for OTG operation".
+	 */
+	/* GCTL.PrtCapDir=2'b11 */
+	dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+	/* GUSB2PHYCFG0.SusPHY=0 */
+	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
+	reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
+
+	/* Initialize OTG registers */
+	dwc3_otgregs_init(dwc);
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	dwc3_otg_fsm_sync(dwc);
+
+	return 0;
+
+error:
+	usb_otg_unregister(dwc->dev);
+
+	return ret;
+}
+
+static void dwc3_drd_exit(struct dwc3 *dwc)
+{
+	free_irq(dwc->otg_irq, dwc);
+	usb_otg_unregister(dwc->dev);
+}
+
+/* -------------------------------------------------------------------------- */
+
 static int dwc3_core_init_mode(struct dwc3 *dwc)
 {
 	struct device *dev = dwc->dev;
@@ -781,11 +1224,31 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
 		}
 		break;
 	case USB_DR_MODE_OTG:
-		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
+		ret = dwc3_drd_init(dwc);
+		if (ret) {
+			if (ret == -EPROBE_DEFER)
+				return ret;
+
+			dev_err(dev,
+				"limiting to peripheral only as dual-role init failed: %d",
+				ret);
+			dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
+			dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
+			ret = dwc3_gadget_init(dwc);
+			if (ret) {
+				if (ret == -EPROBE_DEFER)
+					return ret;
+				dev_err(dev, "failed to initialize gadget\n");
+				return ret;
+			}
+			break;
+		}
+
 		ret = dwc3_host_init(dwc);
 		if (ret) {
 			if (ret != -EPROBE_DEFER)
 				dev_err(dev, "failed to initialize host\n");
+			dwc3_drd_exit(dwc);
 			return ret;
 		}
 
@@ -793,6 +1256,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
 		if (ret) {
 			if (ret != -EPROBE_DEFER)
 				dev_err(dev, "failed to initialize gadget\n");
+			dwc3_host_exit(dwc);
+			dwc3_drd_exit(dwc);
 			return ret;
 		}
 		break;
@@ -816,6 +1281,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
 	case USB_DR_MODE_OTG:
 		dwc3_host_exit(dwc);
 		dwc3_gadget_exit(dwc);
+		dwc3_drd_exit(dwc);
 		break;
 	default:
 		/* do nothing */
@@ -1091,19 +1557,34 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
 {
 	unsigned long	flags;
 
+	spin_lock_irqsave(&dwc->lock, flags);
+
 	switch (dwc->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
-		spin_lock_irqsave(&dwc->lock, flags);
 		dwc3_gadget_suspend(dwc);
-		spin_unlock_irqrestore(&dwc->lock, flags);
+		break;
+	case USB_DR_MODE_OTG:
+		dwc->otg_protocol = dwc->otg->fsm.protocol;
+
+		switch (dwc->otg->fsm.protocol) {
+		case PROTO_GADGET:
+			dwc3_gadget_suspend(dwc);
+			break;
+		case PROTO_HOST:
+		case PROTO_UNDEF:
+		default:
+			/* nothing */
+			break;
+		}
 		break;
 	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_UNKNOWN:
 	default:
 		/* do nothing */
 		break;
 	}
 
+	spin_unlock_irqrestore(&dwc->lock, flags);
 	dwc3_core_exit(dwc);
 
 	return 0;
@@ -1118,19 +1599,41 @@ static int dwc3_resume_common(struct dwc3 *dwc)
 	if (ret)
 		return ret;
 
+	spin_lock_irqsave(&dwc->lock, flags);
+
 	switch (dwc->dr_mode) {
 	case USB_DR_MODE_PERIPHERAL:
-	case USB_DR_MODE_OTG:
-		spin_lock_irqsave(&dwc->lock, flags);
 		dwc3_gadget_resume(dwc);
-		spin_unlock_irqrestore(&dwc->lock, flags);
-		/* FALLTHROUGH */
+		break;
+	case USB_DR_MODE_OTG:
+		switch (dwc->otg_protocol) {
+		case PROTO_GADGET:
+			dwc3_gadget_resume(dwc);
+			break;
+		case PROTO_HOST:
+			break;
+		case PROTO_UNDEF:
+		default:
+			/* nothing */
+			break;
+		}
+		break;
 	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_UNKNOWN:
 	default:
 		/* do nothing */
 		break;
 	}
 
+	/* Restore OTG state only if we're really using it */
+	if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) {
+		dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg);
+		dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl);
+		dwc3_otg_unmask_irq(dwc);
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
 	return 0;
 }
 
@@ -1185,6 +1688,7 @@ static int dwc3_runtime_resume(struct device *dev)
 		dwc3_gadget_process_pending_events(dwc);
 		break;
 	case USB_DR_MODE_HOST:
+	case USB_DR_MODE_UNKNOWN:
 	default:
 		/* do nothing */
 		break;
@@ -1219,6 +1723,30 @@ static int dwc3_runtime_idle(struct device *dev)
 #endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
+static int dwc3_prepare(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	dwc->otg_prevent_sync = true;
+	spin_unlock_irqrestore(&dwc->lock, flags);
+
+	return 0;
+}
+
+static void dwc3_complete(struct device *dev)
+{
+	struct dwc3	*dwc = dev_get_drvdata(dev);
+	unsigned long	flags;
+
+	spin_lock_irqsave(&dwc->lock, flags);
+	dwc->otg_prevent_sync = false;
+	spin_unlock_irqrestore(&dwc->lock, flags);
+	if (dwc->dr_mode == USB_DR_MODE_OTG)
+		dwc3_otg_fsm_sync(dwc);
+}
+
 static int dwc3_suspend(struct device *dev)
 {
 	struct dwc3	*dwc = dev_get_drvdata(dev);
@@ -1256,6 +1784,8 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
 	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
 			dwc3_runtime_idle)
+	.prepare = dwc3_prepare,
+	.complete = dwc3_complete,
 };
 
 #ifdef CONFIG_OF
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 32bb7531..e6b771a 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -31,6 +31,7 @@
 #include <linux/usb/gadget.h>
 #include <linux/usb/otg.h>
 #include <linux/ulpi/interface.h>
+#include <linux/usb/otg-fsm.h>
 
 #include <linux/phy/phy.h>
 
@@ -817,13 +818,21 @@ struct dwc3_scratchpad_array {
  * @gadget_driver: pointer to the gadget driver
  * @regs: base address for our registers
  * @regs_size: address space size
+ * @dr_mode: requested mode of operation
+ * @otg: usb otg data structure
+ * @otg_caps: otg controller capabilities
+ * @otg_config: otg controller configuration
+ * @otg_prevent_sync: flag to block events to otg fsm
+ * @otg_protocol: saved copy of otg state during suspend
+ * @current_mode: current mode of operation written to PRTCAPDIR
+ * @oevt: cached OEVT register during OTG irq
  * @fladj: frame length adjustment
  * @irq_gadget: peripheral controller's IRQ number
+ * @otg_irq: IRQ number for OTG IRQs
  * @nr_scratch: number of scratch buffers
  * @u1u2: only used on revisions <1.83a for workaround
  * @maximum_speed: maximum speed requested (mainly for testing purposes)
  * @revision: revision register contents
- * @dr_mode: requested mode of operation
  * @usb2_phy: pointer to USB2 PHY
  * @usb3_phy: pointer to USB3 PHY
  * @usb2_generic_phy: pointer to USB2 PHY
@@ -831,6 +840,9 @@ struct dwc3_scratchpad_array {
  * @ulpi: pointer to ulpi interface
  * @dcfg: saved contents of DCFG register
  * @gctl: saved contents of GCTL register
+ * @ocfg: saved contents of OCFG register
+ * @octl: saved contents of OCTL register
+ * @oevten: saved contents of OEVTEN register
  * @isoch_delay: wValue from Set Isochronous Delay request;
  * @u2sel: parameter from Set SEL request.
  * @u2pel: parameter from Set SEL request.
@@ -929,9 +941,25 @@ struct dwc3 {
 	size_t			regs_size;
 
 	enum usb_dr_mode	dr_mode;
+	struct usb_otg		*otg;
+	struct usb_otg_caps	otg_caps;
+	struct usb_otg_config	otg_config;
+	bool			otg_prevent_sync;
+	int			otg_protocol;
+	u32			current_mode;
+	u32			oevt;
 
 	u32			fladj;
 	u32			irq_gadget;
+	int			otg_irq;
+
+	/* used for suspend/resume */
+	u32			dcfg;
+	u32			gctl;
+	u32			ocfg;
+	u32			octl;
+	u32			oevten;
+
 	u32			nr_scratch;
 	u32			u1u2;
 	u32			maximum_speed;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1ade5e8..e409b1e 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2974,7 +2974,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
 	if (ret)
 		goto err5;
 
-	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
+	if (dwc->dr_mode == USB_DR_MODE_OTG)
+		ret = usb_otg_add_gadget_udc(dwc->dev, &dwc->gadget, dwc->dev);
+	else
+		ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
+
 	if (ret) {
 		dev_err(dwc->dev, "failed to register udc\n");
 		goto err5;
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index 2e960ed..32096ec 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -91,6 +91,8 @@ int dwc3_host_init(struct dwc3 *dwc)
 	memset(&pdata, 0, sizeof(pdata));
 
 	pdata.usb3_lpm_capable = dwc->usb3_lpm_capable;
+	if (dwc->dr_mode == USB_DR_MODE_OTG)
+		pdata.otg_dev = dwc->dev;
 
 	ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
 	if (ret) {
-- 
2.7.4

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

* [PATCH v7 3/4] ARM: dts: dra7*-evm: Enable dual-role for usb1
  2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
  2016-06-10 13:17 ` [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions Roger Quadros
  2016-06-10 13:17 ` [PATCH v7 2/4] usb: dwc3: add dual-role support Roger Quadros
@ 2016-06-10 13:17 ` Roger Quadros
  2016-06-10 13:17 ` [PATCH v7 4/4] ARM: dts: am43xx: Enable dual-role on USB1 Roger Quadros
  2016-06-10 13:26 ` [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
  4 siblings, 0 replies; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:17 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

Now that we have dual-role support working at USB core,
enable dual-role support for usb1 controller.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/boot/dts/dra7-evm.dts          | 5 ++++-
 arch/arm/boot/dts/dra72-evm-common.dtsi | 5 ++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index bafcfac..75a4065 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -731,7 +731,10 @@
 };
 
 &usb1 {
-	dr_mode = "peripheral";
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb1_pins>;
 };
diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi
index 093538e..24ad2ff 100644
--- a/arch/arm/boot/dts/dra72-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra72-evm-common.dtsi
@@ -571,7 +571,10 @@
 };
 
 &usb2 {
-	dr_mode = "host";
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb2_pins>;
 };
-- 
2.7.4

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

* [PATCH v7 4/4] ARM: dts: am43xx: Enable dual-role on USB1
  2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
                   ` (2 preceding siblings ...)
  2016-06-10 13:17 ` [PATCH v7 3/4] ARM: dts: dra7*-evm: Enable dual-role for usb1 Roger Quadros
@ 2016-06-10 13:17 ` Roger Quadros
  2016-06-10 13:26 ` [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
  4 siblings, 0 replies; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:17 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

USB1 port is micro-AB type and can function as peripheral
as well as host. Enable dual-role mode for USB1.

Signed-off-by: Roger Quadros <rogerq@ti.com>
---
 arch/arm/boot/dts/am437x-gp-evm.dts  | 5 ++++-
 arch/arm/boot/dts/am437x-sk-evm.dts  | 5 ++++-
 arch/arm/boot/dts/am43x-epos-evm.dts | 5 ++++-
 3 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/arm/boot/dts/am437x-gp-evm.dts b/arch/arm/boot/dts/am437x-gp-evm.dts
index 5bcd3aa..d76a885 100644
--- a/arch/arm/boot/dts/am437x-gp-evm.dts
+++ b/arch/arm/boot/dts/am437x-gp-evm.dts
@@ -765,7 +765,10 @@
 };
 
 &usb1 {
-	dr_mode = "peripheral";
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
 	status = "okay";
 };
 
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index d82dd6e..b11d50e 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -571,8 +571,11 @@
 };
 
 &usb1 {
-	dr_mode = "peripheral";
 	status = "okay";
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
 	pinctrl-names = "default";
 	pinctrl-0 = <&usb1_pins>;
 };
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 3549b8c..9578602 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -676,8 +676,11 @@
 };
 
 &usb1 {
-	dr_mode = "peripheral";
 	status = "okay";
+	dr_mode = "otg";
+	hnp-disable;
+	srp-disable;
+	adp-disable;
 };
 
 &usb2_phy2 {
-- 
2.7.4

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

* Re: [PATCH v7 0/4] usb: dwc3: dual-role support
  2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
                   ` (3 preceding siblings ...)
  2016-06-10 13:17 ` [PATCH v7 4/4] ARM: dts: am43xx: Enable dual-role on USB1 Roger Quadros
@ 2016-06-10 13:26 ` Roger Quadros
  4 siblings, 0 replies; 12+ messages in thread
From: Roger Quadros @ 2016-06-10 13:26 UTC (permalink / raw)
  To: balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap

On 10/06/16 16:17, Roger Quadros wrote:
> Hi,
> 
> This series adds dual role support to dwc3 controller driver.
> Series depends on the OTG/dual-role framework [1].
> 
> [1] - http://thread.gmane.org/gmane.linux.usb.general/143568
> 
> Patches are based on Felipe's balbi/usb.git testing/next

This patch is also a pre-requisite for this series.
http://article.gmane.org/gmane.linux.kernel/2240761

> 
> Changelog:
> 
> v7:
> - rebased to v4.7-rc1 + balbi/usb.git testing/next
> - cleaned up otg irq resource code
> 
> v6:
> - use just otg irq to get otg events and don't depend on extcon at all.
> - follow OTG flow in TRM strictly.
> - use tracepoints instead of dev_dbg().
> - match IRQ flags in dwc3_omap and core.c for shared otg interrupt.
> 
> v5: Internal revision. Not sent to mailing list.
> 
> v4: first version that was reviewed.
> 
> cheers,
> -roger
> 
> 
> Roger Quadros (4):
>   usb: dwc3: core.h: add some register definitions
>   usb: dwc3: add dual-role support
>   ARM: dts: dra7*-evm: Enable dual-role for usb1
>   ARM: dts: am43xx: Enable dual-role on USB1
> 
>  arch/arm/boot/dts/am437x-gp-evm.dts     |   5 +-
>  arch/arm/boot/dts/am437x-sk-evm.dts     |   5 +-
>  arch/arm/boot/dts/am43x-epos-evm.dts    |   5 +-
>  arch/arm/boot/dts/dra7-evm.dts          |   5 +-
>  arch/arm/boot/dts/dra72-evm-common.dtsi |   5 +-
>  drivers/usb/dwc3/core.c                 | 546 +++++++++++++++++++++++++++++++-
>  drivers/usb/dwc3/core.h                 | 114 ++++++-
>  drivers/usb/dwc3/gadget.c               |   6 +-
>  drivers/usb/dwc3/host.c                 |   2 +
>  9 files changed, 677 insertions(+), 16 deletions(-)
> 

--
cheers,
-roger

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

* Re: [PATCH v7 2/4] usb: dwc3: add dual-role support
  2016-06-10 13:17 ` [PATCH v7 2/4] usb: dwc3: add dual-role support Roger Quadros
@ 2016-06-12  9:11   ` Peter Chen
  2016-06-13  7:09     ` Roger Quadros
  0 siblings, 1 reply; 12+ messages in thread
From: Peter Chen @ 2016-06-12  9:11 UTC (permalink / raw)
  To: Roger Quadros
  Cc: balbi, tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap

On Fri, Jun 10, 2016 at 04:17:28PM +0300, Roger Quadros wrote:
> Register with the USB OTG/DRD core. Since we don't support
> OTG yet we just work as a dual-role device even
> if device tree says "otg".
> 
> Get ID and VBUS information from the OTG controller
> and kick the OTG state machine.
> 

Hi Roger,

I can't apply it after rebase usb-next rc1 and felipe's testing/next.
How to apply it?

Peter
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> ---
>  drivers/usb/dwc3/core.c   | 546 +++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/usb/dwc3/core.h   |  30 ++-
>  drivers/usb/dwc3/gadget.c |   6 +-
>  drivers/usb/dwc3/host.c   |   2 +
>  4 files changed, 574 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
> index d51c9a9..28d2da2 100644
> --- a/drivers/usb/dwc3/core.c
> +++ b/drivers/usb/dwc3/core.c
> @@ -56,6 +56,7 @@ void dwc3_set_mode(struct dwc3 *dwc, u32 mode)
>  	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
>  	reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
>  	reg |= DWC3_GCTL_PRTCAPDIR(mode);
> +	dwc->current_mode = mode;
>  	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
>  }
>  
> @@ -756,6 +757,448 @@ static int dwc3_core_get_phy(struct dwc3 *dwc)
>  	return 0;
>  }
>  
> +/* Get OTG events and sync it to OTG fsm */
> +static void dwc3_otg_fsm_sync(struct dwc3 *dwc)
> +{
> +	u32 reg;
> +	int id, vbus;
> +
> +	/*
> +	 * calling usb_otg_sync_inputs() during resume breaks host
> +	 * if adapter was removed during suspend as xhci driver
> +	 * is not prepared to see hcd removal before xhci_resume.
> +	 */
> +	if (dwc->otg_prevent_sync)
> +		return;
> +
> +	reg = dwc3_readl(dwc->regs, DWC3_OSTS);
> +	dwc3_trace(trace_dwc3_core, "otgstatus 0x%x\n", reg);
> +
> +	id = !!(reg & DWC3_OSTS_CONIDSTS);
> +	vbus = !!(reg & DWC3_OSTS_BSESVLD);
> +
> +	dwc3_trace(trace_dwc3_core, "id %d vbus %d\n", id, vbus);
> +	dwc->otg->fsm.id = id;
> +	dwc->otg->fsm.b_sess_vld = vbus;
> +	usb_otg_sync_inputs(dwc->otg);
> +}
> +
> +static void dwc3_otg_mask_irq(struct dwc3 *dwc)
> +{
> +	dwc->oevten = dwc3_readl(dwc->regs, DWC3_OEVTEN);
> +	dwc3_writel(dwc->regs, DWC3_OEVTEN, 0);
> +}
> +
> +static void dwc3_otg_unmask_irq(struct dwc3 *dwc)
> +{
> +	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
> +}
> +
> +static void dwc3_otg_disable_events(struct dwc3 *dwc, u32 disable_mask)
> +{
> +	dwc->oevten &= ~(disable_mask);
> +	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
> +}
> +
> +static void dwc3_otg_enable_events(struct dwc3 *dwc, u32 enable_mask)
> +{
> +	dwc->oevten |= (enable_mask);
> +	dwc3_writel(dwc->regs, DWC3_OEVTEN, dwc->oevten);
> +}
> +
> +#define DWC3_OTG_ALL_EVENTS	(DWC3_OEVTEN_XHCIRUNSTPSETEN | \
> +		DWC3_OEVTEN_DEVRUNSTPSETEN | DWC3_OEVTEN_HIBENTRYEN | \
> +		DWC3_OEVTEN_CONIDSTSCHNGEN | DWC3_OEVTEN_HRRCONFNOTIFEN | \
> +		DWC3_OEVTEN_HRRINITNOTIFEN | DWC3_OEVTEN_ADEVIDLEEN | \
> +		DWC3_OEVTEN_ADEVBHOSTENDEN | DWC3_OEVTEN_ADEVHOSTEN | \
> +		DWC3_OEVTEN_ADEVHNPCHNGEN | DWC3_OEVTEN_ADEVSRPDETEN | \
> +		DWC3_OEVTEN_ADEVSESSENDDETEN | DWC3_OEVTEN_BDEVHOSTENDEN | \
> +		DWC3_OEVTEN_BDEVHNPCHNGEN | DWC3_OEVTEN_BDEVSESSVLDDETEN | \
> +		DWC3_OEVTEN_BDEVVBUSCHNGE)
> +
> +static int dwc3_drd_start_host(struct usb_otg *otg, int on);
> +static int dwc3_drd_start_gadget(struct usb_otg *otg, int on);
> +static irqreturn_t dwc3_otg_thread_irq(int irq, void *_dwc)
> +{
> +	struct dwc3 *dwc = _dwc;
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&dwc->lock, flags);
> +
> +	/*
> +	 * this bit is needed for otg-host to work after system suspend/resume
> +	 */
> +	if ((dwc->otg->state == OTG_STATE_A_HOST) &&
> +	    !(dwc->oevt & DWC3_OEVT_DEVICEMODE)) {
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +		dwc3_drd_start_host(dwc->otg, true);
> +		spin_lock_irqsave(&dwc->lock, flags);
> +	}
> +
> +	dwc3_otg_fsm_sync(dwc);
> +	dwc3_otg_unmask_irq(dwc);
> +
> +	dwc->oevt = 0;
> +	spin_unlock_irqrestore(&dwc->lock, flags);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static irqreturn_t dwc3_otg_irq(int irq, void *_dwc)
> +{
> +	struct dwc3 *dwc = _dwc;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 reg;
> +
> +	reg = dwc3_readl(dwc->regs, DWC3_OEVT);
> +	if (reg) {
> +		dwc->oevt = reg;
> +		dwc3_writel(dwc->regs, DWC3_OEVT, reg);
> +		dwc3_otg_mask_irq(dwc);
> +		ret = IRQ_WAKE_THREAD;
> +	}
> +
> +	return ret;
> +}
> +
> +/* --------------------- Dual-Role management ------------------------------- */
> +static void dwc3_otgregs_init(struct dwc3 *dwc)
> +{
> +	u32 reg;
> +
> +	/*
> +	 * Prevent host/device reset from resetting OTG core.
> +	 * If we don't do this then xhci_reset (USBCMD.HCRST) will reset
> +	 * the signal outputs sent to the PHY, the OTG FSM logic of the
> +	 * core and also the resets to the VBUS filters inside the core.
> +	 */
> +	reg = dwc3_readl(dwc->regs, DWC3_OCFG);
> +	reg |= DWC3_OCFG_SFTRSTMASK;
> +	dwc3_writel(dwc->regs, DWC3_OCFG, reg);
> +
> +	/* Disable hibernation for simplicity */
> +	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> +	reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
> +	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> +
> +	/*
> +	 * Initialize OTG registers as per
> +	 * Figure 11-4 OTG Driver Overall Programming Flow
> +	 */
> +	/* OCFG.SRPCap = 0, OCFG.HNPCap = 0 */
> +	reg = dwc3_readl(dwc->regs, DWC3_OCFG);
> +	reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
> +	dwc3_writel(dwc->regs, DWC3_OCFG, reg);
> +	/* OEVT = FFFF */
> +	dwc3_writel(dwc->regs, DWC3_OEVT, ~0);
> +	/* OEVTEN = 0 */
> +	dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
> +	/* OEVTEN.ConIDStsChngEn = 1. Instead we enable all events */
> +	dwc3_otg_enable_events(dwc, DWC3_OTG_ALL_EVENTS);
> +	/*
> +	 * OCTL.PeriMode = 1, OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0,
> +	 * OCTL.HNPReq = 0
> +	 */
> +	reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +	reg |= DWC3_OCTL_PERIMODE;
> +	reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN |
> +		 DWC3_OCTL_HNPREQ);
> +	dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +}
> +
> +static int dwc3_drd_start_host(struct usb_otg *otg, int on)
> +{
> +	struct dwc3 *dwc = dev_get_drvdata(otg->dev);
> +	u32 reg;
> +	unsigned long flags;
> +
> +	dwc3_trace(trace_dwc3_core, "%s: %d\n", __func__, on);
> +
> +	/* switch OTG core */
> +	if (on) {
> +		/* As per Figure 11-10 A-Device Flow Diagram */
> +
> +		spin_lock_irqsave(&dwc->lock, flags);
> +		/* OCFG.HNPCap = 0, OCFG.SRPCap = 0 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
> +		reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
> +		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
> +
> +		/*
> +		 * OCTL.PeriMode=0, OCTL.TermSelDLPulse = 0,
> +		 * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
> +		 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +		reg &= ~(DWC3_OCTL_PERIMODE | DWC3_OCTL_TERMSELIDPULSE |
> +			 DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
> +		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +
> +		/*
> +		 * OCFG.DisPrtPwrCutoff = 0/1
> +		 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
> +		reg &= ~DWC3_OCFG_DISPWRCUTTOFF;
> +		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
> +
> +		/* start the xHCI host driver */
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +		usb_otg_start_host(otg, true);
> +		spin_lock_irqsave(&dwc->lock, flags);
> +
> +		/*
> +		 * OCFG.SRPCap = 1, OCFG.HNPCap = GHWPARAMS6.HNP_CAP
> +		 * We don't want SRP/HNP for simple dual-role so leave
> +		 * these disabled.
> +		 */
> +
> +		/*
> +		 * OEVTEN.OTGADevHostEvntEn = 1
> +		 * OEVTEN.OTGADevSessEndDetEvntEn = 1
> +		 * We don't want HNP/role-swap so leave these disabled.
> +		 */
> +
> +		/* GUSB2PHYCFG.ULPIAutoRes = 1/0, GUSB2PHYCFG.SusPHY = 1 */
> +		if (!dwc->dis_u2_susphy_quirk) {
> +			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
> +			reg |= DWC3_GUSB2PHYCFG_SUSPHY;
> +			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
> +		}
> +
> +		/* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +		reg |= DWC3_OCTL_PRTPWRCTL;
> +		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +	} else {
> +		/*
> +		 * Exit from A-device flow as per
> +		 * Figure 11-4 OTG Driver Overall Programming Flow
> +		 */
> +		/* stop the HCD */
> +		usb_otg_start_host(otg, false);
> +
> +		spin_lock_irqsave(&dwc->lock, flags);
> +		/*
> +		 * OEVTEN.OTGADevBHostEndEvntEn=0, OEVTEN.OTGADevHNPChngEvntEn=0
> +		 * OEVTEN.OTGADevSessEndDetEvntEn=0,
> +		 * OEVTEN.OTGADevHostEvntEn = 0
> +		 * But we don't disable any OTG events
> +		 */
> +
> +		/* OCTL.HstSetHNPEn = 0, OCTL.PrtPwrCtl=0 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +		reg &= ~(DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_PRTPWRCTL);
> +		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +
> +		/* Initialize OTG registers */
> +		dwc3_otgregs_init(dwc);
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static int dwc3_drd_start_gadget(struct usb_otg *otg, int on)
> +{
> +	struct dwc3 *dwc = dev_get_drvdata(otg->dev);
> +	u32 reg;
> +	unsigned long flags;
> +
> +	dwc3_trace(trace_dwc3_core, "%s: %d\n", __func__, on);
> +	if (on)
> +		dwc3_event_buffers_setup(dwc);
> +
> +	if (on) {
> +		/* As per Figure 11-20 B-Device Flow Diagram */
> +
> +		spin_lock_irqsave(&dwc->lock, flags);
> +		/*
> +		 * OCFG.HNPCap = GHWPARAMS6.HNP_CAP, OCFG.SRPCap = 1
> +		 * but we set them to 0 for simple dual-role operation.
> +		 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCFG);
> +		reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
> +		/* OCFG.OTGSftRstMsk = 0/1 */
> +		reg |= DWC3_OCFG_SFTRSTMASK;
> +		dwc3_writel(dwc->regs, DWC3_OCFG, reg);
> +		/*
> +		 * OCTL.PeriMode = 1
> +		 * OCTL.TermSelDLPulse = 0/1, OCTL.HNPReq = 0
> +		 * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
> +		 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +		reg |= DWC3_OCTL_PERIMODE;
> +		reg &= ~(DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_HNPREQ |
> +			 DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
> +		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +		/* OEVTEN.OTGBDevSesVldDetEvntEn = 1 */
> +		dwc3_otg_enable_events(dwc, DWC3_OEVT_BDEVSESSVLDDET);
> +		/* GUSB2PHYCFG.ULPIAutoRes = 0, GUSB2PHYCFG0.SusPHY = 1 */
> +		if (!dwc->dis_u2_susphy_quirk) {
> +			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
> +			reg |= DWC3_GUSB2PHYCFG_SUSPHY;
> +			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
> +		}
> +		/* GCTL.GblHibernationEn = 0 */
> +		reg = dwc3_readl(dwc->regs, DWC3_GCTL);
> +		reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
> +		dwc3_writel(dwc->regs, DWC3_GCTL, reg);
> +
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +
> +		/* start the Peripheral driver  */
> +		usb_otg_start_gadget(otg, true);
> +	} else {
> +		/*
> +		 * Exit from B-device flow as per
> +		 * Figure 11-4 OTG Driver Overall Programming Flow
> +		 */
> +		/* stop the Peripheral driver */
> +		usb_otg_start_gadget(otg, false);
> +
> +		spin_lock_irqsave(&dwc->lock, flags);
> +
> +		/*
> +		 * OEVTEN.OTGBDevHNPChngEvntEn = 0
> +		 * OEVTEN.OTGBDevVBusChngEvntEn = 0
> +		 * OEVTEN.OTGBDevBHostEndEvntEn = 0
> +		 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
> +		reg &= ~(DWC3_OEVT_BDEVHNPCHNG | DWC3_OEVT_BDEVVBUSCHNG |
> +			 DWC3_OEVT_BDEVBHOSTEND);
> +		dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
> +
> +		/* OCTL.DevSetHNPEn = 0, OCTL.HNPReq = 0, OCTL.PeriMode=1 */
> +		reg = dwc3_readl(dwc->regs, DWC3_OCTL);
> +		reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HNPREQ);
> +		reg |= DWC3_OCTL_PERIMODE;
> +		dwc3_writel(dwc->regs, DWC3_OCTL, reg);
> +
> +		/* Initialize OTG registers */
> +		dwc3_otgregs_init(dwc);
> +		spin_unlock_irqrestore(&dwc->lock, flags);
> +	}
> +
> +	return 0;
> +}
> +
> +static struct otg_fsm_ops dwc3_drd_ops = {
> +	.start_host = dwc3_drd_start_host,
> +	.start_gadget = dwc3_drd_start_gadget,
> +};
> +
> +static int dwc3_drd_register(struct dwc3 *dwc)
> +{
> +	int ret;
> +
> +	/* register parent as DRD device with OTG core */
> +	dwc->otg = usb_otg_register(dwc->dev, &dwc->otg_config);
> +	if (IS_ERR(dwc->otg)) {
> +		ret = PTR_ERR(dwc->otg);
> +		if (ret == -ENOTSUPP)
> +			dev_err(dwc->dev, "CONFIG_USB_OTG needed for dual-role\n");
> +		else
> +			dev_err(dwc->dev, "Failed to register with OTG core\n");
> +
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int dwc3_drd_init(struct dwc3 *dwc)
> +{
> +	int ret, irq;
> +	struct usb_otg_caps *otgcaps = &dwc->otg_caps;
> +	u32 reg;
> +	unsigned long flags;
> +	struct platform_device *dwc3_pdev = to_platform_device(dwc->dev);
> +
> +	irq = platform_get_irq_byname(dwc3_pdev, "otg");
> +	if (irq == -EPROBE_DEFER)
> +		return irq;
> +
> +	if (irq <= 0) {
> +		irq = platform_get_irq_byname(dwc3_pdev, "dwc_usb3");
> +		if (irq == -EPROBE_DEFER)
> +			return irq;
> +
> +		if (irq <= 0) {
> +			irq = platform_get_irq(dwc3_pdev, 0);
> +			if (irq <= 0) {
> +				if (irq != -EPROBE_DEFER)
> +					dev_err(dwc->dev, "missing otg IRQ\n");
> +
> +				if (!irq)
> +					irq = -EINVAL;
> +				return irq;
> +			}
> +		}
> +	}
> +
> +	dwc->otg_irq = irq;
> +
> +	otgcaps->otg_rev = 0;
> +	otgcaps->hnp_support = false;
> +	otgcaps->srp_support = false;
> +	otgcaps->adp_support = false;
> +	dwc->otg_config.fsm_ops = &dwc3_drd_ops;
> +	dwc->otg_config.otg_caps = otgcaps;
> +
> +	ret = dwc3_drd_register(dwc);
> +	if (ret)
> +		return ret;
> +
> +	/* disable all otg irqs */
> +	dwc3_otg_disable_events(dwc, DWC3_OTG_ALL_EVENTS);
> +	/* clear all events */
> +	dwc3_writel(dwc->regs, DWC3_OEVT, ~0);
> +
> +	ret = request_threaded_irq(dwc->otg_irq, dwc3_otg_irq,
> +				   dwc3_otg_thread_irq,
> +				   IRQF_SHARED, "dwc3-otg", dwc);
> +	if (ret) {
> +		dev_err(dwc->dev, "failed to request irq #%d --> %d\n",
> +			dwc->otg_irq, ret);
> +		ret = -ENODEV;
> +		goto error;
> +	}
> +
> +	spin_lock_irqsave(&dwc->lock, flags);
> +
> +	/*
> +	 * As per Figure 11-4 OTG Driver Overall Programming Flow,
> +	 * block "Initialize GCTL for OTG operation".
> +	 */
> +	/* GCTL.PrtCapDir=2'b11 */
> +	dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
> +	/* GUSB2PHYCFG0.SusPHY=0 */
> +	reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
> +	reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
> +	dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
> +
> +	/* Initialize OTG registers */
> +	dwc3_otgregs_init(dwc);
> +	spin_unlock_irqrestore(&dwc->lock, flags);
> +
> +	dwc3_otg_fsm_sync(dwc);
> +
> +	return 0;
> +
> +error:
> +	usb_otg_unregister(dwc->dev);
> +
> +	return ret;
> +}
> +
> +static void dwc3_drd_exit(struct dwc3 *dwc)
> +{
> +	free_irq(dwc->otg_irq, dwc);
> +	usb_otg_unregister(dwc->dev);
> +}
> +
> +/* -------------------------------------------------------------------------- */
> +
>  static int dwc3_core_init_mode(struct dwc3 *dwc)
>  {
>  	struct device *dev = dwc->dev;
> @@ -781,11 +1224,31 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
>  		}
>  		break;
>  	case USB_DR_MODE_OTG:
> -		dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG);
> +		ret = dwc3_drd_init(dwc);
> +		if (ret) {
> +			if (ret == -EPROBE_DEFER)
> +				return ret;
> +
> +			dev_err(dev,
> +				"limiting to peripheral only as dual-role init failed: %d",
> +				ret);
> +			dwc->dr_mode = USB_DR_MODE_PERIPHERAL;
> +			dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_DEVICE);
> +			ret = dwc3_gadget_init(dwc);
> +			if (ret) {
> +				if (ret == -EPROBE_DEFER)
> +					return ret;
> +				dev_err(dev, "failed to initialize gadget\n");
> +				return ret;
> +			}
> +			break;
> +		}
> +
>  		ret = dwc3_host_init(dwc);
>  		if (ret) {
>  			if (ret != -EPROBE_DEFER)
>  				dev_err(dev, "failed to initialize host\n");
> +			dwc3_drd_exit(dwc);
>  			return ret;
>  		}
>  
> @@ -793,6 +1256,8 @@ static int dwc3_core_init_mode(struct dwc3 *dwc)
>  		if (ret) {
>  			if (ret != -EPROBE_DEFER)
>  				dev_err(dev, "failed to initialize gadget\n");
> +			dwc3_host_exit(dwc);
> +			dwc3_drd_exit(dwc);
>  			return ret;
>  		}
>  		break;
> @@ -816,6 +1281,7 @@ static void dwc3_core_exit_mode(struct dwc3 *dwc)
>  	case USB_DR_MODE_OTG:
>  		dwc3_host_exit(dwc);
>  		dwc3_gadget_exit(dwc);
> +		dwc3_drd_exit(dwc);
>  		break;
>  	default:
>  		/* do nothing */
> @@ -1091,19 +1557,34 @@ static int dwc3_suspend_common(struct dwc3 *dwc)
>  {
>  	unsigned long	flags;
>  
> +	spin_lock_irqsave(&dwc->lock, flags);
> +
>  	switch (dwc->dr_mode) {
>  	case USB_DR_MODE_PERIPHERAL:
> -	case USB_DR_MODE_OTG:
> -		spin_lock_irqsave(&dwc->lock, flags);
>  		dwc3_gadget_suspend(dwc);
> -		spin_unlock_irqrestore(&dwc->lock, flags);
> +		break;
> +	case USB_DR_MODE_OTG:
> +		dwc->otg_protocol = dwc->otg->fsm.protocol;
> +
> +		switch (dwc->otg->fsm.protocol) {
> +		case PROTO_GADGET:
> +			dwc3_gadget_suspend(dwc);
> +			break;
> +		case PROTO_HOST:
> +		case PROTO_UNDEF:
> +		default:
> +			/* nothing */
> +			break;
> +		}
>  		break;
>  	case USB_DR_MODE_HOST:
> +	case USB_DR_MODE_UNKNOWN:
>  	default:
>  		/* do nothing */
>  		break;
>  	}
>  
> +	spin_unlock_irqrestore(&dwc->lock, flags);
>  	dwc3_core_exit(dwc);
>  
>  	return 0;
> @@ -1118,19 +1599,41 @@ static int dwc3_resume_common(struct dwc3 *dwc)
>  	if (ret)
>  		return ret;
>  
> +	spin_lock_irqsave(&dwc->lock, flags);
> +
>  	switch (dwc->dr_mode) {
>  	case USB_DR_MODE_PERIPHERAL:
> -	case USB_DR_MODE_OTG:
> -		spin_lock_irqsave(&dwc->lock, flags);
>  		dwc3_gadget_resume(dwc);
> -		spin_unlock_irqrestore(&dwc->lock, flags);
> -		/* FALLTHROUGH */
> +		break;
> +	case USB_DR_MODE_OTG:
> +		switch (dwc->otg_protocol) {
> +		case PROTO_GADGET:
> +			dwc3_gadget_resume(dwc);
> +			break;
> +		case PROTO_HOST:
> +			break;
> +		case PROTO_UNDEF:
> +		default:
> +			/* nothing */
> +			break;
> +		}
> +		break;
>  	case USB_DR_MODE_HOST:
> +	case USB_DR_MODE_UNKNOWN:
>  	default:
>  		/* do nothing */
>  		break;
>  	}
>  
> +	/* Restore OTG state only if we're really using it */
> +	if (dwc->current_mode == DWC3_GCTL_PRTCAP_OTG) {
> +		dwc3_writel(dwc->regs, DWC3_OCFG, dwc->ocfg);
> +		dwc3_writel(dwc->regs, DWC3_OCTL, dwc->octl);
> +		dwc3_otg_unmask_irq(dwc);
> +	}
> +
> +	spin_unlock_irqrestore(&dwc->lock, flags);
> +
>  	return 0;
>  }
>  
> @@ -1185,6 +1688,7 @@ static int dwc3_runtime_resume(struct device *dev)
>  		dwc3_gadget_process_pending_events(dwc);
>  		break;
>  	case USB_DR_MODE_HOST:
> +	case USB_DR_MODE_UNKNOWN:
>  	default:
>  		/* do nothing */
>  		break;
> @@ -1219,6 +1723,30 @@ static int dwc3_runtime_idle(struct device *dev)
>  #endif /* CONFIG_PM */
>  
>  #ifdef CONFIG_PM_SLEEP
> +static int dwc3_prepare(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	unsigned long	flags;
> +
> +	spin_lock_irqsave(&dwc->lock, flags);
> +	dwc->otg_prevent_sync = true;
> +	spin_unlock_irqrestore(&dwc->lock, flags);
> +
> +	return 0;
> +}
> +
> +static void dwc3_complete(struct device *dev)
> +{
> +	struct dwc3	*dwc = dev_get_drvdata(dev);
> +	unsigned long	flags;
> +
> +	spin_lock_irqsave(&dwc->lock, flags);
> +	dwc->otg_prevent_sync = false;
> +	spin_unlock_irqrestore(&dwc->lock, flags);
> +	if (dwc->dr_mode == USB_DR_MODE_OTG)
> +		dwc3_otg_fsm_sync(dwc);
> +}
> +
>  static int dwc3_suspend(struct device *dev)
>  {
>  	struct dwc3	*dwc = dev_get_drvdata(dev);
> @@ -1256,6 +1784,8 @@ static const struct dev_pm_ops dwc3_dev_pm_ops = {
>  	SET_SYSTEM_SLEEP_PM_OPS(dwc3_suspend, dwc3_resume)
>  	SET_RUNTIME_PM_OPS(dwc3_runtime_suspend, dwc3_runtime_resume,
>  			dwc3_runtime_idle)
> +	.prepare = dwc3_prepare,
> +	.complete = dwc3_complete,
>  };
>  
>  #ifdef CONFIG_OF
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 32bb7531..e6b771a 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -31,6 +31,7 @@
>  #include <linux/usb/gadget.h>
>  #include <linux/usb/otg.h>
>  #include <linux/ulpi/interface.h>
> +#include <linux/usb/otg-fsm.h>
>  
>  #include <linux/phy/phy.h>
>  
> @@ -817,13 +818,21 @@ struct dwc3_scratchpad_array {
>   * @gadget_driver: pointer to the gadget driver
>   * @regs: base address for our registers
>   * @regs_size: address space size
> + * @dr_mode: requested mode of operation
> + * @otg: usb otg data structure
> + * @otg_caps: otg controller capabilities
> + * @otg_config: otg controller configuration
> + * @otg_prevent_sync: flag to block events to otg fsm
> + * @otg_protocol: saved copy of otg state during suspend
> + * @current_mode: current mode of operation written to PRTCAPDIR
> + * @oevt: cached OEVT register during OTG irq
>   * @fladj: frame length adjustment
>   * @irq_gadget: peripheral controller's IRQ number
> + * @otg_irq: IRQ number for OTG IRQs
>   * @nr_scratch: number of scratch buffers
>   * @u1u2: only used on revisions <1.83a for workaround
>   * @maximum_speed: maximum speed requested (mainly for testing purposes)
>   * @revision: revision register contents
> - * @dr_mode: requested mode of operation
>   * @usb2_phy: pointer to USB2 PHY
>   * @usb3_phy: pointer to USB3 PHY
>   * @usb2_generic_phy: pointer to USB2 PHY
> @@ -831,6 +840,9 @@ struct dwc3_scratchpad_array {
>   * @ulpi: pointer to ulpi interface
>   * @dcfg: saved contents of DCFG register
>   * @gctl: saved contents of GCTL register
> + * @ocfg: saved contents of OCFG register
> + * @octl: saved contents of OCTL register
> + * @oevten: saved contents of OEVTEN register
>   * @isoch_delay: wValue from Set Isochronous Delay request;
>   * @u2sel: parameter from Set SEL request.
>   * @u2pel: parameter from Set SEL request.
> @@ -929,9 +941,25 @@ struct dwc3 {
>  	size_t			regs_size;
>  
>  	enum usb_dr_mode	dr_mode;
> +	struct usb_otg		*otg;
> +	struct usb_otg_caps	otg_caps;
> +	struct usb_otg_config	otg_config;
> +	bool			otg_prevent_sync;
> +	int			otg_protocol;
> +	u32			current_mode;
> +	u32			oevt;
>  
>  	u32			fladj;
>  	u32			irq_gadget;
> +	int			otg_irq;
> +
> +	/* used for suspend/resume */
> +	u32			dcfg;
> +	u32			gctl;
> +	u32			ocfg;
> +	u32			octl;
> +	u32			oevten;
> +
>  	u32			nr_scratch;
>  	u32			u1u2;
>  	u32			maximum_speed;
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 1ade5e8..e409b1e 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -2974,7 +2974,11 @@ int dwc3_gadget_init(struct dwc3 *dwc)
>  	if (ret)
>  		goto err5;
>  
> -	ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
> +	if (dwc->dr_mode == USB_DR_MODE_OTG)
> +		ret = usb_otg_add_gadget_udc(dwc->dev, &dwc->gadget, dwc->dev);
> +	else
> +		ret = usb_add_gadget_udc(dwc->dev, &dwc->gadget);
> +
>  	if (ret) {
>  		dev_err(dwc->dev, "failed to register udc\n");
>  		goto err5;
> diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
> index 2e960ed..32096ec 100644
> --- a/drivers/usb/dwc3/host.c
> +++ b/drivers/usb/dwc3/host.c
> @@ -91,6 +91,8 @@ int dwc3_host_init(struct dwc3 *dwc)
>  	memset(&pdata, 0, sizeof(pdata));
>  
>  	pdata.usb3_lpm_capable = dwc->usb3_lpm_capable;
> +	if (dwc->dr_mode == USB_DR_MODE_OTG)
> +		pdata.otg_dev = dwc->dev;
>  
>  	ret = platform_device_add_data(xhci, &pdata, sizeof(pdata));
>  	if (ret) {
> -- 
> 2.7.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 

Best Regards,
Peter Chen

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

* Re: [PATCH v7 2/4] usb: dwc3: add dual-role support
  2016-06-12  9:11   ` Peter Chen
@ 2016-06-13  7:09     ` Roger Quadros
  2016-06-13  8:25       ` Roger Quadros
  0 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2016-06-13  7:09 UTC (permalink / raw)
  To: Peter Chen
  Cc: balbi, tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap

Peter,

On 12/06/16 12:11, Peter Chen wrote:
> On Fri, Jun 10, 2016 at 04:17:28PM +0300, Roger Quadros wrote:
>> Register with the USB OTG/DRD core. Since we don't support
>> OTG yet we just work as a dual-role device even
>> if device tree says "otg".
>>
>> Get ID and VBUS information from the OTG controller
>> and kick the OTG state machine.
>>
> 
> Hi Roger,
> 
> I can't apply it after rebase usb-next rc1 and felipe's testing/next.
> How to apply it?

You just need to apply the series on Felipe's testing/next + this one patch
http://article.gmane.org/gmane.linux.kernel/2240761

--
cheers,
-roger

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

* Re: [PATCH v7 2/4] usb: dwc3: add dual-role support
  2016-06-13  7:09     ` Roger Quadros
@ 2016-06-13  8:25       ` Roger Quadros
  0 siblings, 0 replies; 12+ messages in thread
From: Roger Quadros @ 2016-06-13  8:25 UTC (permalink / raw)
  To: Peter Chen
  Cc: balbi, tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap

On 13/06/16 10:09, Roger Quadros wrote:
> Peter,
> 
> On 12/06/16 12:11, Peter Chen wrote:
>> On Fri, Jun 10, 2016 at 04:17:28PM +0300, Roger Quadros wrote:
>>> Register with the USB OTG/DRD core. Since we don't support
>>> OTG yet we just work as a dual-role device even
>>> if device tree says "otg".
>>>
>>> Get ID and VBUS information from the OTG controller
>>> and kick the OTG state machine.
>>>
>>
>> Hi Roger,
>>
>> I can't apply it after rebase usb-next rc1 and felipe's testing/next.
>> How to apply it?
> 
> You just need to apply the series on Felipe's testing/next + this one patch
> http://article.gmane.org/gmane.linux.kernel/2240761

You can also use the below repo as balbi testing/next is a moving target

https://github.com/rogerq/linux/commits/for-v4.8/otg-drd-v11-core-dwc3-v7

--
cheers,
-roger

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

* Re: [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions
  2016-06-10 13:17 ` [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions Roger Quadros
@ 2016-06-20  9:28   ` Felipe Balbi
  2016-06-20 11:53     ` Roger Quadros
  0 siblings, 1 reply; 12+ messages in thread
From: Felipe Balbi @ 2016-06-20  9:28 UTC (permalink / raw)
  To: Roger Quadros
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap, Roger Quadros

[-- Attachment #1: Type: text/plain, Size: 1533 bytes --]


Hi,

Roger Quadros <rogerq@ti.com> writes:
> Add OTG and GHWPARAMS6 register definitions
>
> Signed-off-by: Roger Quadros <rogerq@ti.com>
> ---
>  drivers/usb/dwc3/core.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 83 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
> index 8fb6361..32bb7531 100644
> --- a/drivers/usb/dwc3/core.h
> +++ b/drivers/usb/dwc3/core.h
> @@ -197,6 +197,15 @@
>  #define DWC3_GCTL_GBLHIBERNATIONEN	(1 << 1)
>  #define DWC3_GCTL_DSBLCLKGTNG		(1 << 0)
>  
> +/* Global Status Register */
> +#define DWC3_GSTS_OTG_IP	BIT(10)
> +#define DWC3_GSTS_BC_IP		BIT(9)
> +#define DWC3_GSTS_ADP_IP	BIT(8)
> +#define DWC3_GSTS_HOST_IP	BIT(7)
> +#define DWC3_GSTS_DEVICE_IP	BIT(6)
> +#define DWC3_GSTS_CSR_TIMEOUT	BIT(5)
> +#define DWC3_GSTS_BUS_ERR_ADDR_VLD	BIT(4)
> +
>  /* Global USB2 PHY Configuration Register */
>  #define DWC3_GUSB2PHYCFG_PHYSOFTRST	(1 << 31)
>  #define DWC3_GUSB2PHYCFG_SUSPHY		(1 << 6)
> @@ -269,7 +278,12 @@
>  #define DWC3_MAX_HIBER_SCRATCHBUFS		15
>  
>  /* Global HWPARAMS6 Register */
> -#define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
> +#define DWC3_GHWPARAMS6_BCSUPPORT		BIT(14)
> +#define DWC3_GHWPARAMS6_OTG3SUPPORT		BIT(13)
> +#define DWC3_GHWPARAMS6_ADPSUPPORT		BIT(12)
> +#define DWC3_GHWPARAMS6_HNPSUPPORT		BIT(11)
> +#define DWC3_GHWPARAMS6_SRPSUPPORT		BIT(10)
> +#define DWC3_GHWPARAMS6_EN_FPGA			BIT(7)

Keep consistency, we don't use BIT() here.

-- 
balbi

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

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

* Re: [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions
  2016-06-20  9:28   ` Felipe Balbi
@ 2016-06-20 11:53     ` Roger Quadros
  2016-06-20 12:04       ` Felipe Balbi
  0 siblings, 1 reply; 12+ messages in thread
From: Roger Quadros @ 2016-06-20 11:53 UTC (permalink / raw)
  To: Felipe Balbi
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap


[-- Attachment #1.1: Type: text/plain, Size: 1720 bytes --]

On 20/06/16 12:28, Felipe Balbi wrote:
> 
> Hi,
> 
> Roger Quadros <rogerq@ti.com> writes:
>> Add OTG and GHWPARAMS6 register definitions
>>
>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>> ---
>>  drivers/usb/dwc3/core.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>  1 file changed, 83 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>> index 8fb6361..32bb7531 100644
>> --- a/drivers/usb/dwc3/core.h
>> +++ b/drivers/usb/dwc3/core.h
>> @@ -197,6 +197,15 @@
>>  #define DWC3_GCTL_GBLHIBERNATIONEN	(1 << 1)
>>  #define DWC3_GCTL_DSBLCLKGTNG		(1 << 0)
>>  
>> +/* Global Status Register */
>> +#define DWC3_GSTS_OTG_IP	BIT(10)
>> +#define DWC3_GSTS_BC_IP		BIT(9)
>> +#define DWC3_GSTS_ADP_IP	BIT(8)
>> +#define DWC3_GSTS_HOST_IP	BIT(7)
>> +#define DWC3_GSTS_DEVICE_IP	BIT(6)
>> +#define DWC3_GSTS_CSR_TIMEOUT	BIT(5)
>> +#define DWC3_GSTS_BUS_ERR_ADDR_VLD	BIT(4)
>> +
>>  /* Global USB2 PHY Configuration Register */
>>  #define DWC3_GUSB2PHYCFG_PHYSOFTRST	(1 << 31)
>>  #define DWC3_GUSB2PHYCFG_SUSPHY		(1 << 6)
>> @@ -269,7 +278,12 @@
>>  #define DWC3_MAX_HIBER_SCRATCHBUFS		15
>>  
>>  /* Global HWPARAMS6 Register */
>> -#define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
>> +#define DWC3_GHWPARAMS6_BCSUPPORT		BIT(14)
>> +#define DWC3_GHWPARAMS6_OTG3SUPPORT		BIT(13)
>> +#define DWC3_GHWPARAMS6_ADPSUPPORT		BIT(12)
>> +#define DWC3_GHWPARAMS6_HNPSUPPORT		BIT(11)
>> +#define DWC3_GHWPARAMS6_SRPSUPPORT		BIT(10)
>> +#define DWC3_GHWPARAMS6_EN_FPGA			BIT(7)
> 
> Keep consistency, we don't use BIT() here.
> 
Checkpatch was complaining. But I can revert to the non BIT format for
consistency.

cheers,
-roger


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions
  2016-06-20 11:53     ` Roger Quadros
@ 2016-06-20 12:04       ` Felipe Balbi
  0 siblings, 0 replies; 12+ messages in thread
From: Felipe Balbi @ 2016-06-20 12:04 UTC (permalink / raw)
  To: Roger Quadros
  Cc: tony, Joao.Pinto, sergei.shtylyov, peter.chen, jun.li,
	grygorii.strashko, yoshihiro.shimoda.uh, nsekhar, linux-usb,
	linux-kernel, linux-omap

[-- Attachment #1: Type: text/plain, Size: 1838 bytes --]


Hi,

Roger Quadros <rogerq@ti.com> writes:
>> Roger Quadros <rogerq@ti.com> writes:
>>> Add OTG and GHWPARAMS6 register definitions
>>>
>>> Signed-off-by: Roger Quadros <rogerq@ti.com>
>>> ---
>>>  drivers/usb/dwc3/core.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++-
>>>  1 file changed, 83 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
>>> index 8fb6361..32bb7531 100644
>>> --- a/drivers/usb/dwc3/core.h
>>> +++ b/drivers/usb/dwc3/core.h
>>> @@ -197,6 +197,15 @@
>>>  #define DWC3_GCTL_GBLHIBERNATIONEN	(1 << 1)
>>>  #define DWC3_GCTL_DSBLCLKGTNG		(1 << 0)
>>>  
>>> +/* Global Status Register */
>>> +#define DWC3_GSTS_OTG_IP	BIT(10)
>>> +#define DWC3_GSTS_BC_IP		BIT(9)
>>> +#define DWC3_GSTS_ADP_IP	BIT(8)
>>> +#define DWC3_GSTS_HOST_IP	BIT(7)
>>> +#define DWC3_GSTS_DEVICE_IP	BIT(6)
>>> +#define DWC3_GSTS_CSR_TIMEOUT	BIT(5)
>>> +#define DWC3_GSTS_BUS_ERR_ADDR_VLD	BIT(4)
>>> +
>>>  /* Global USB2 PHY Configuration Register */
>>>  #define DWC3_GUSB2PHYCFG_PHYSOFTRST	(1 << 31)
>>>  #define DWC3_GUSB2PHYCFG_SUSPHY		(1 << 6)
>>> @@ -269,7 +278,12 @@
>>>  #define DWC3_MAX_HIBER_SCRATCHBUFS		15
>>>  
>>>  /* Global HWPARAMS6 Register */
>>> -#define DWC3_GHWPARAMS6_EN_FPGA			(1 << 7)
>>> +#define DWC3_GHWPARAMS6_BCSUPPORT		BIT(14)
>>> +#define DWC3_GHWPARAMS6_OTG3SUPPORT		BIT(13)
>>> +#define DWC3_GHWPARAMS6_ADPSUPPORT		BIT(12)
>>> +#define DWC3_GHWPARAMS6_HNPSUPPORT		BIT(11)
>>> +#define DWC3_GHWPARAMS6_SRPSUPPORT		BIT(10)
>>> +#define DWC3_GHWPARAMS6_EN_FPGA			BIT(7)
>> 
>> Keep consistency, we don't use BIT() here.
>> 
> Checkpatch was complaining.

then you should first convert everything to BIT() first, right?

> But I can revert to the non BIT format for consistency.

works for me.

-- 
balbi

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 818 bytes --]

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

end of thread, other threads:[~2016-06-20 12:10 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-10 13:17 [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros
2016-06-10 13:17 ` [PATCH v7 1/4] usb: dwc3: core.h: add some register definitions Roger Quadros
2016-06-20  9:28   ` Felipe Balbi
2016-06-20 11:53     ` Roger Quadros
2016-06-20 12:04       ` Felipe Balbi
2016-06-10 13:17 ` [PATCH v7 2/4] usb: dwc3: add dual-role support Roger Quadros
2016-06-12  9:11   ` Peter Chen
2016-06-13  7:09     ` Roger Quadros
2016-06-13  8:25       ` Roger Quadros
2016-06-10 13:17 ` [PATCH v7 3/4] ARM: dts: dra7*-evm: Enable dual-role for usb1 Roger Quadros
2016-06-10 13:17 ` [PATCH v7 4/4] ARM: dts: am43xx: Enable dual-role on USB1 Roger Quadros
2016-06-10 13:26 ` [PATCH v7 0/4] usb: dwc3: dual-role support Roger Quadros

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).