[RFC/PATCH v4] usb: dwc3: Introduce OTG driver for dwc3
This is first release of otg driver for the dwc3 Synopsys USB3 core. The otg driver implements the otg final state machine and control the activation of the device controller or host controller. In this first implementation, only simple DRD mode is implemented, determine if A or B device according to the ID pin as reflected in the OSTS.ConIDSts field. Signed-off-by: Ido Shayevitz i...@codeaurora.org --- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 55 - drivers/usb/dwc3/dwc3_otg.c | 537 ++ drivers/usb/dwc3/dwc3_otg.h | 59 + drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 8 files changed, 755 insertions(+), 10 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..ffb3f55 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,11 +1,13 @@ ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG +ccflags-y += -Idrivers/usb/host obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o dwc3-y += host.o dwc3-y += gadget.o ep0.o +dwc3-y += dwc3_otg.o ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); + ret = dwc3_otg_init(dwc); + if (ret) { + dev_err(dev, failed to initialize otg\n); + goto err1; + } + ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); + dwc3_otg_exit(dwc); goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, failed to initialize gadget\n); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); goto err1; } break; @@ -554,8 +563,9 @@ err2: dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ @@ -588,8 +598,9 @@ static int __devexit dwc3_remove(struct platform_device *pdev) dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c611d80..c2521ba 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -50,6 +50,8 @@ #include linux/usb/ch9.h #include linux/usb/gadget.h +#include dwc3_otg.h + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -152,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN0xcc08 -#define DWC3_OSTS 0xcc0C +#define DWC3_OEVT 0xcc08 +#define DWC3_OEVTEN0xcc0c +#define DWC3_OSTS 0xcc10 /* Bit fields */ @@ -203,6 +206,9 @@ #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) (0x0f 13)) 13) #define DWC3_MAX_HIBER_SCRATCHBUFS 15 +/* Global HWPARAMS6 Register */ +#define DWC3_GHWPARAMS6_SRP_SUPPORT(1 10) + /* Device Configuration Register */ #define DWC3_DCFG_LPM_CAP (1 22) #define DWC3_DCFG_DEVADDR(addr)((addr) 3) @@ -358,6 +364,38 @@ #define DWC3_DEPCMD_TYPE_BULK 2 #define DWC3_DEPCMD_TYPE_INTR 3 +/* OTG Events Register */ +#define DWC3_OEVT_DEVICEMODE (1 31) +#define DWC3_OEVT_CLEAR_ALL(~DWC3_OEVT_DEVICEMODE) +#define DWC3_OEVTEN_OTGCONIDSTSCHNGEVNT(1 24) +#define DWC3_OEVTEN_OTGADEVBHOSTENDEVNT(1 20) +#define DWC3_OEVTEN_OTGADEVHOSTEVNT(1 19) +#define DWC3_OEVTEN_OTGADEVHNPCHNGEVNT (1 18) +#define DWC3_OEVTEN_OTGADEVSRPDETEVNT
RE: [RFC/PATCH v3] usb: dwc3: Introduce OTG driver for dwc3
Hi Paul, On Mon, July 30, 2012 12:00 pm, Paul Zimmerman wrote: From: Ido Shayevitz [mailto:i...@codeaurora.org] Sent: Monday, July 30, 2012 3:15 AM On Thu, July 26, 2012 4:38 pm, Paul Zimmerman wrote: From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb-ow...@vger.kernel.org] On Behalf Of Ido Shayevitz Sent: Wednesday, July 25, 2012 5:46 AM --- drivers/usb/dwc3/Kconfig |6 +- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 54 +- drivers/usb/dwc3/dwc3_otg.c | 512 ++ drivers/usb/dwc3/dwc3_otg.h | 38 +++ drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 9 files changed, 711 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f..0cc108d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,9 +1,9 @@ config USB_DWC3 tristate DesignWare USB3 DRD Core Support - depends on (USB USB_GADGET) + depends on (USB || USB_GADGET) Are you sure this is correct? How can a dual-role device work unless both USB and USB_GADGET are set? If the USB_DWC3 is not selected then even dwc3/core.c is not being built and core.c supports also non DRD cores (depends on DWC3_MODE), so we want to build the DWC3 if there is at least host support or a gadget support. In case that the DWC_MODE is DRD but USB is not on, then dwc3/host.c will add the xHCI device, but will be no xHCI driver (xhci-plat) that will probe on this device. I just tried compiling this without USB_GADGET defined, and I get these errors: HOSTCC arch/x86/boot/compressed/mkpiggy ERROR: usb_gadget_map_request [drivers/usb/dwc3/dwc3.ko] undefined! ERROR: usb_del_gadget_udc [drivers/usb/dwc3/dwc3.ko] undefined! ERROR: usb_gadget_unmap_request [drivers/usb/dwc3/dwc3.ko] undefined! ERROR: usb_add_gadget_udc [drivers/usb/dwc3/dwc3.ko] undefined! Yes, you are totally right. So we have two options: The first is, if you agree with my reasoning: and core.c supports also non DRD cores (depends on DWC3_MODE), so we want to build the DWC3 if there is at least host support or a gadget support. Then we may want to build gadget.c and ep0.c only if USB_GADGET is selected and this requires also changes in core.c or core.h (providing empty prototype for dwc3_gadget_init() ?) The second option is indeed to keep it as it is, means USB USB_GADGET. It means that kernel image size will have to include xHCI driver and dwc3 gadget driver, nevertheless if the controller is DRD or not. Basically I am ok with that too. Please let me know what you and Felipe decide... diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); + ret = dwc3_otg_init(dwc); + if (ret) { + dev_err(dev, failed to initialize otg\n); + goto err1; + } + You should follow the existing pattern for error handling in this function. If there is an error, jump to the error exit, and put your exit function there, instead of here. I think I followed the pattern for error handling in this function. Please see that it is the same as case DWC3_MODE_HOST or case DWC3_MODE_DEVICE ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); + dwc3_otg_exit(dwc); Same here. Here I was thinking of moving dwc3_otg_exit() to the error handling section, but I think it will make the error handling section too clumsy since eventhough the mode is DWC3_MODE_DRD, in this point I want to exit only the otg and not the host or gadget. So this should have a new error label that will be located between err1 and err2. On the other hand if the error will happen later, as the goto err2 statement below in this function, then if the mode is DRD I will want to activate the exit function of also the host and gadget but not doing the otg exit again (the new label) and then do err1... So it becomes clumsy. Yes, I see now that the error handling for DRD in that function was broken before your patch, and your patch fixes it. So it's up to Felipe to decide if the way you did it is acceptable. -- Paul -- To unsubscribe from this list: send the line unsubscribe linux-usb in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Ido -- Consultant for Qualcomm Innovation
RE: [RFC/PATCH v3] usb: dwc3: Introduce OTG driver for dwc3
Hi Anton, On Tue, July 31, 2012 11:27 pm, Anton Tikhomirov wrote: Hi Ido, -Original Message- From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb- ow...@vger.kernel.org] On Behalf Of Ido Shayevitz Sent: Monday, July 30, 2012 10:16 PM To: Anton Tikhomirov Cc: 'Ido Shayevitz'; 'Felipe Balbi'; linux-usb@vger.kernel.org Subject: RE: [RFC/PATCH v3] usb: dwc3: Introduce OTG driver for dwc3 Hi Anton, On Mon, July 30, 2012 5:25 am, Anton Tikhomirov wrote: Hi Ido, You activate sm only if gadget and host are ready. At the same time, in dwc3_otg_interrupt() you schedule work if interrupt happens. In situation when host is not set yet, but cable is plugged, we will have unwanted sm activation (in interrupt handler) and, as a consequence, repeating error unable to start A-device\n in dwc3_otg_sm_work(). Host and gadget should set themselves to the otg on drivers probe, in boot time. So cable connect happens later. If the scenario you describe does happen it means that the xHCI driver was not loaded into the kernel, but cable with micro-A was plugged into your device, so need add host support to the menuconfig. It should be enough to select in the menuconfig CONFIG_USB and CONFIG_USB_XHCI_HCD. Agree. But what if my controller supports DRD mode, but I _want_ to keep this option (XHCI support) off, for any reason. By the way, it seems we will have similar effect when micro-A cable is plugged after otg_set_host(phy-otg, NULL) call. Of course such situations are rare. OK, so I will avoid the re-schedule of the sm_work after this error will be printed (so will be printed once...) Thanks... One more thing. Currently the work is first time scheduled in two cases: when interrupt happens or both, peripheral and host, were set. If host is not set (and probably won't be) the work will _not_ be scheduled (and peripheral will not start) till we connect and then disconnect micro-A cable. In other words: we should be able to use peripheral even if host is not supported (and vice versa?). What's your opinion? The idea behind schedule the work after both are set, is that we don't want a case that we scheduled the work after only the gadget was set but the ID pin is zero. In this case we will get wasted run of work state machine. If host is not set, we will start the peripheral on cable connect, as you said, and if ID pin is 1. When we start the peripheral we actually just turn on the run stop bit, while the dwc3 gadget driver was already up and allocated its needed memory, so there shouldn't be problem to wait until cable connect... But if your controller DWC_MODE (see core.c) does not support DRD, or the cable plugged in is micro-B then this error should not be printed eventhough the host was not set. + } else { + if (otg-phy-state == OTG_STATE_A_HOST) { + dwc3_otg_start_host(otg, 0); + otg-host = NULL; + otg-phy-state = OTG_STATE_UNDEFINED; + schedule_work(dotg-sm_work); + } else { + otg-host = NULL; + } + } + + return 0; +} + +/** + * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. + * + * @otg: Pointer to the otg_transceiver structure. + * @gadget: pointer to the usb_gadget structure. This comment doesn't match the function definition (@on, not @gadget). + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) +{ + struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); + + if (!otg-gadget) + return -EINVAL; + + if (on) { + dev_dbg(otg-phy-dev, %s: turn on gadget %s\n, + __func__, otg-gadget-name); + dwc3_otg_set_peripheral_regs(dotg); + usb_gadget_vbus_connect(otg-gadget); + } else { + dev_dbg(otg-phy-dev, %s: turn off gadget %s\n, + __func__, otg-gadget-name); + usb_gadget_vbus_disconnect(otg-gadget); + } + + return 0; +} + +/** + * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver. + * + * @otg: Pointer to the otg_transceiver structure. + * @gadget: pointer to the usb_gadget structure. + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) +{ + struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); + + if (gadget) { + dev_dbg(otg-phy-dev, %s: set gadget %s\n, + __func__, gadget
RE: [RFC/PATCH v3] usb: dwc3: Introduce OTG driver for dwc3
Hi Anton, On Mon, July 30, 2012 5:25 am, Anton Tikhomirov wrote: Hi Ido, You activate sm only if gadget and host are ready. At the same time, in dwc3_otg_interrupt() you schedule work if interrupt happens. In situation when host is not set yet, but cable is plugged, we will have unwanted sm activation (in interrupt handler) and, as a consequence, repeating error unable to start A-device\n in dwc3_otg_sm_work(). Host and gadget should set themselves to the otg on drivers probe, in boot time. So cable connect happens later. If the scenario you describe does happen it means that the xHCI driver was not loaded into the kernel, but cable with micro-A was plugged into your device, so need add host support to the menuconfig. It should be enough to select in the menuconfig CONFIG_USB and CONFIG_USB_XHCI_HCD. Agree. But what if my controller supports DRD mode, but I _want_ to keep this option (XHCI support) off, for any reason. By the way, it seems we will have similar effect when micro-A cable is plugged after otg_set_host(phy-otg, NULL) call. Of course such situations are rare. OK, so I will avoid the re-schedule of the sm_work after this error will be printed (so will be printed once...) Thanks... But if your controller DWC_MODE (see core.c) does not support DRD, or the cable plugged in is micro-B then this error should not be printed eventhough the host was not set. + } else { + if (otg-phy-state == OTG_STATE_A_HOST) { + dwc3_otg_start_host(otg, 0); + otg-host = NULL; + otg-phy-state = OTG_STATE_UNDEFINED; + schedule_work(dotg-sm_work); + } else { + otg-host = NULL; + } + } + + return 0; +} + +/** + * dwc3_otg_start_peripheral - bind/unbind the peripheral controller. + * + * @otg: Pointer to the otg_transceiver structure. + * @gadget: pointer to the usb_gadget structure. This comment doesn't match the function definition (@on, not @gadget). + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on) +{ + struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); + + if (!otg-gadget) + return -EINVAL; + + if (on) { + dev_dbg(otg-phy-dev, %s: turn on gadget %s\n, + __func__, otg-gadget-name); + dwc3_otg_set_peripheral_regs(dotg); + usb_gadget_vbus_connect(otg-gadget); + } else { + dev_dbg(otg-phy-dev, %s: turn off gadget %s\n, + __func__, otg-gadget-name); + usb_gadget_vbus_disconnect(otg-gadget); + } + + return 0; +} + +/** + * dwc3_otg_set_peripheral - bind/unbind the peripheral controller driver. + * + * @otg: Pointer to the otg_transceiver structure. + * @gadget: pointer to the usb_gadget structure. + * + * Returns 0 on success otherwise negative errno. + */ +static int dwc3_otg_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) +{ + struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg); + + if (gadget) { + dev_dbg(otg-phy-dev, %s: set gadget %s\n, + __func__, gadget-name); + otg-gadget = gadget; + + /* + * Only after both peripheral and host are set then check + * OTG sm. This prevents unnecessary activation of the sm + * in case the ID is grounded. + */ + if (otg-host) + schedule_work(dotg-sm_work); + } else { + if (otg-phy-state == OTG_STATE_B_PERIPHERAL) { + dwc3_otg_start_peripheral(otg, 0); + otg-gadget = NULL; + otg-phy-state = OTG_STATE_UNDEFINED; + schedule_work(dotg-sm_work); + } else { + otg-gadget = NULL; + } + } + + return 0; +} + +/** + * dwc3_otg_interrupt - interrupt handler for dwc3 otg events. You forgot about @irq here. + * @_dotg: Pointer to out controller context structure + * + * Returns IRQ_HANDLED on success otherwise IRQ_NONE. + */ +static irqreturn_t dwc3_otg_interrupt(int irq, void *_dotg) +{ + struct dwc3_otg *dotg = (struct dwc3_otg *)_dotg; + u32 oevt_reg; + int ret = IRQ_NONE; + u32 handled_irqs = 0; + + oevt_reg = dwc3_readl(dotg-regs, DWC3_OEVT); + + if (oevt_reg
RE: [RFC/PATCH v2] usb: dwc3: Introduce OTG driver for dwc3
Hi Anton, On Tue, July 17, 2012 9:27 pm, Anton Tikhomirov wrote: Hi, -Original Message- From: linux-usb-ow...@vger.kernel.org [mailto:linux-usb- ow...@vger.kernel.org] On Behalf Of Ido Shayevitz Sent: Thursday, July 12, 2012 1:24 AM To: ba...@ti.com Cc: linux-usb@vger.kernel.org; i...@codeaurora.org Subject: [RFC/PATCH v2] usb: dwc3: Introduce OTG driver for dwc3 This is first release of otg driver for the dwc3 Synopsys USB3 core. The otg driver implements the otg final state machine and control the activation of the device controller or host controller. In this first implementation, only simple DRD mode is implemented, determine if A or B device according to the ID pin as reflected in the OSTS.ConIDSts field. Signed-off-by: Ido Shayevitz i...@codeaurora.org --- drivers/usb/dwc3/Kconfig |6 +- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 51 - drivers/usb/dwc3/dwc3_otg.c | 512 ++ drivers/usb/dwc3/dwc3_otg.h | 38 +++ drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 9 files changed, 708 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f..0cc108d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,9 +1,9 @@ config USB_DWC3 tristate DesignWare USB3 DRD Core Support -depends on (USB USB_GADGET) +depends on (USB || USB_GADGET) select USB_OTG_UTILS -select USB_GADGET_DUALSPEED -select USB_GADGET_SUPERSPEED +select USB_GADGET_DUALSPEED if USB_GADGET +select USB_GADGET_SUPERSPEED if USB_GADGET select USB_XHCI_PLATFORM if USB_SUPPORT USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..ffb3f55 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,11 +1,13 @@ ccflags-$(CONFIG_USB_DWC3_DEBUG):= -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG +ccflags-y += -Idrivers/usb/host obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o dwc3-y += host.o dwc3-y += gadget.o ep0.o +dwc3-y += dwc3_otg.o ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); +ret = dwc3_otg_init(dwc); +if (ret) { +dev_err(dev, failed to initialize otg\n); +goto err1; +} + ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); +dwc3_otg_exit(dwc); goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, failed to initialize gadget\n); +dwc3_host_exit(dwc); +dwc3_otg_exit(dwc); goto err1; } break; @@ -554,8 +563,9 @@ err2: dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: -dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); +dwc3_host_exit(dwc); +dwc3_otg_exit(dwc); break; default: /* do nothing */ @@ -588,8 +598,9 @@ static int __devexit dwc3_remove(struct platform_device *pdev) dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: -dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); +dwc3_host_exit(dwc); +dwc3_otg_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca8..793758b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -50,6 +50,8 @@ #include linux/usb/ch9.h #include linux/usb/gadget.h +#include dwc3_otg.h + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE512 #define DWC3_ENDPOINTS_NUM 32 @@ -152,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN 0xcc08 -#define DWC3_OSTS
[RFC/PATCH v3] usb: dwc3: Introduce OTG driver for dwc3
This is first release of otg driver for the dwc3 Synopsys USB3 core. The otg driver implements the otg final state machine and control the activation of the device controller or host controller. In this first implementation, only simple DRD mode is implemented, determine if A or B device according to the ID pin as reflected in the OSTS.ConIDSts field. Signed-off-by: Ido Shayevitz i...@codeaurora.org --- drivers/usb/dwc3/Kconfig |6 +- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 54 +- drivers/usb/dwc3/dwc3_otg.c | 512 ++ drivers/usb/dwc3/dwc3_otg.h | 38 +++ drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 9 files changed, 711 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f..0cc108d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,9 +1,9 @@ config USB_DWC3 tristate DesignWare USB3 DRD Core Support - depends on (USB USB_GADGET) + depends on (USB || USB_GADGET) select USB_OTG_UTILS - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED + select USB_GADGET_DUALSPEED if USB_GADGET + select USB_GADGET_SUPERSPEED if USB_GADGET select USB_XHCI_PLATFORM if USB_SUPPORT USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..ffb3f55 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,11 +1,13 @@ ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG +ccflags-y += -Idrivers/usb/host obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o dwc3-y += host.o dwc3-y += gadget.o ep0.o +dwc3-y += dwc3_otg.o ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); + ret = dwc3_otg_init(dwc); + if (ret) { + dev_err(dev, failed to initialize otg\n); + goto err1; + } + ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); + dwc3_otg_exit(dwc); goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, failed to initialize gadget\n); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); goto err1; } break; @@ -554,8 +563,9 @@ err2: dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ @@ -588,8 +598,9 @@ static int __devexit dwc3_remove(struct platform_device *pdev) dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index c611d80..29a03e0 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -50,6 +50,8 @@ #include linux/usb/ch9.h #include linux/usb/gadget.h +#include dwc3_otg.h + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -152,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN0xcc08 -#define DWC3_OSTS 0xcc0C +#define DWC3_OEVT 0xcc08 +#define DWC3_OEVTEN0xcc0c +#define DWC3_OSTS 0xcc10 /* Bit fields */ @@ -203,6 +206,9 @@ #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) (0x0f 13)) 13) #define DWC3_MAX_HIBER_SCRATCHBUFS 15 +/* Global HWPARAMS6 Register */ +#define
[RFC/PATCH] usb: dwc3: Introduce OTG driver for dwc3
This is first release of otg driver for the dwc3 Synopsys USB3 core. The otg driver implements the otg final state machine and control the activation of the device controller or host controller. In this first implementation, only simple DRD mode is implemented, determine if A or B device according to the ID pin as reflected in the OSTS.ConIDSts field. Signed-off-by: Ido Shayevitz i...@codeaurora.org --- drivers/usb/dwc3/Kconfig |6 +- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 51 - drivers/usb/dwc3/dwc3_otg.c | 512 ++ drivers/usb/dwc3/dwc3_otg.h | 38 +++ drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 9 files changed, 708 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f..0cc108d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,9 +1,9 @@ config USB_DWC3 tristate DesignWare USB3 DRD Core Support - depends on (USB USB_GADGET) + depends on (USB || USB_GADGET) select USB_OTG_UTILS - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED + select USB_GADGET_DUALSPEED if USB_GADGET + select USB_GADGET_SUPERSPEED if USB_GADGET select USB_XHCI_PLATFORM if USB_SUPPORT USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..ffb3f55 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,11 +1,13 @@ ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG +ccflags-y += -Idrivers/usb/host obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o dwc3-y += host.o dwc3-y += gadget.o ep0.o +dwc3-y += dwc3_otg.o ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); + ret = dwc3_otg_init(dwc); + if (ret) { + dev_err(dev, failed to initialize otg\n); + goto err1; + } + ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); + dwc3_otg_exit(dwc); goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, failed to initialize gadget\n); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); goto err1; } break; @@ -554,8 +563,9 @@ err2: dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ @@ -588,8 +598,9 @@ static int __devexit dwc3_remove(struct platform_device *pdev) dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca8..793758b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -50,6 +50,8 @@ #include linux/usb/ch9.h #include linux/usb/gadget.h +#include dwc3_otg.h + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -152,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN0xcc08 -#define DWC3_OSTS 0xcc0C +#define DWC3_OEVT 0xcc08 +#define DWC3_OEVTEN0xcc0c +#define DWC3_OSTS 0xcc10 /* Bit fields */ @@ -203,6 +206,9 @@ #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) (0x0f 13)) 13) #define DWC3_MAX_HIBER_SCRATCHBUFS 15 +/* Global HWPARAMS6 Register */ +#define
[RFC/PATCH v2] usb: dwc3: Introduce OTG driver for dwc3
This is first release of otg driver for the dwc3 Synopsys USB3 core. The otg driver implements the otg final state machine and control the activation of the device controller or host controller. In this first implementation, only simple DRD mode is implemented, determine if A or B device according to the ID pin as reflected in the OSTS.ConIDSts field. Signed-off-by: Ido Shayevitz i...@codeaurora.org --- drivers/usb/dwc3/Kconfig |6 +- drivers/usb/dwc3/Makefile|2 + drivers/usb/dwc3/core.c | 15 +- drivers/usb/dwc3/core.h | 51 - drivers/usb/dwc3/dwc3_otg.c | 512 ++ drivers/usb/dwc3/dwc3_otg.h | 38 +++ drivers/usb/dwc3/gadget.c| 63 + drivers/usb/host/xhci-plat.c | 21 ++ drivers/usb/host/xhci.c | 13 +- 9 files changed, 708 insertions(+), 13 deletions(-) create mode 100644 drivers/usb/dwc3/dwc3_otg.c create mode 100644 drivers/usb/dwc3/dwc3_otg.h diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f..0cc108d 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,9 +1,9 @@ config USB_DWC3 tristate DesignWare USB3 DRD Core Support - depends on (USB USB_GADGET) + depends on (USB || USB_GADGET) select USB_OTG_UTILS - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED + select USB_GADGET_DUALSPEED if USB_GADGET + select USB_GADGET_SUPERSPEED if USB_GADGET select USB_XHCI_PLATFORM if USB_SUPPORT USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile index d441fe4..ffb3f55 100644 --- a/drivers/usb/dwc3/Makefile +++ b/drivers/usb/dwc3/Makefile @@ -1,11 +1,13 @@ ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG ccflags-$(CONFIG_USB_DWC3_VERBOSE) += -DVERBOSE_DEBUG +ccflags-y += -Idrivers/usb/host obj-$(CONFIG_USB_DWC3) += dwc3.o dwc3-y := core.o dwc3-y += host.o dwc3-y += gadget.o ep0.o +dwc3-y += dwc3_otg.o ifneq ($(CONFIG_DEBUG_FS),) dwc3-y += debugfs.o diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..5343e39 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -517,15 +517,24 @@ static int __devinit dwc3_probe(struct platform_device *pdev) break; case DWC3_MODE_DRD: dwc3_set_mode(dwc, DWC3_GCTL_PRTCAP_OTG); + ret = dwc3_otg_init(dwc); + if (ret) { + dev_err(dev, failed to initialize otg\n); + goto err1; + } + ret = dwc3_host_init(dwc); if (ret) { dev_err(dev, failed to initialize host\n); + dwc3_otg_exit(dwc); goto err1; } ret = dwc3_gadget_init(dwc); if (ret) { dev_err(dev, failed to initialize gadget\n); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); goto err1; } break; @@ -554,8 +563,9 @@ err2: dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ @@ -588,8 +598,9 @@ static int __devexit dwc3_remove(struct platform_device *pdev) dwc3_host_exit(dwc); break; case DWC3_MODE_DRD: - dwc3_host_exit(dwc); dwc3_gadget_exit(dwc); + dwc3_host_exit(dwc); + dwc3_otg_exit(dwc); break; default: /* do nothing */ diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca8..793758b 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -50,6 +50,8 @@ #include linux/usb/ch9.h #include linux/usb/gadget.h +#include dwc3_otg.h + /* Global constants */ #define DWC3_EP0_BOUNCE_SIZE 512 #define DWC3_ENDPOINTS_NUM 32 @@ -152,8 +154,9 @@ /* OTG Registers */ #define DWC3_OCFG 0xcc00 #define DWC3_OCTL 0xcc04 -#define DWC3_OEVTEN0xcc08 -#define DWC3_OSTS 0xcc0C +#define DWC3_OEVT 0xcc08 +#define DWC3_OEVTEN0xcc0c +#define DWC3_OSTS 0xcc10 /* Bit fields */ @@ -203,6 +206,9 @@ #define DWC3_GHWPARAMS4_HIBER_SCRATCHBUFS(n) (((n) (0x0f 13)) 13) #define DWC3_MAX_HIBER_SCRATCHBUFS 15 +/* Global HWPARAMS6 Register */ +#define