Module Name: src
Committed By: skrll
Date: Sun Aug 30 12:59:59 UTC 2015
Modified Files:
src/sys/external/bsd/dwc2/dist: dwc2_core.c dwc2_core.h dwc2_coreintr.c
dwc2_hcd.c dwc2_hcd.h dwc2_hcdintr.c dwc2_hcdqueue.c dwc2_hw.h
Log Message:
Merge conflicts
To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/sys/external/bsd/dwc2/dist/dwc2_core.c
cvs rdiff -u -r1.5 -r1.6 src/sys/external/bsd/dwc2/dist/dwc2_core.h
cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c
cvs rdiff -u -r1.15 -r1.16 src/sys/external/bsd/dwc2/dist/dwc2_hcd.c
cvs rdiff -u -r1.9 -r1.10 src/sys/external/bsd/dwc2/dist/dwc2_hcd.h
cvs rdiff -u -r1.11 -r1.12 src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c \
src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c
cvs rdiff -u -r1.2 -r1.3 src/sys/external/bsd/dwc2/dist/dwc2_hw.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/external/bsd/dwc2/dist/dwc2_core.c
diff -u src/sys/external/bsd/dwc2/dist/dwc2_core.c:1.7 src/sys/external/bsd/dwc2/dist/dwc2_core.c:1.8
--- src/sys/external/bsd/dwc2/dist/dwc2_core.c:1.7 Fri May 1 06:58:40 2015
+++ src/sys/external/bsd/dwc2/dist/dwc2_core.c Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_core.c,v 1.7 2015/05/01 06:58:40 hikaru Exp $ */
+/* $NetBSD: dwc2_core.c,v 1.8 2015/08/30 12:59:59 skrll Exp $ */
/*
* core.c - DesignWare HS OTG Controller common routines
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_core.c,v 1.7 2015/05/01 06:58:40 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_core.c,v 1.8 2015/08/30 12:59:59 skrll Exp $");
#include <sys/types.h>
#include <sys/bus.h>
@@ -67,6 +67,364 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2_core.c,
#include "dwc2_core.h"
#include "dwc2_hcd.h"
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+/**
+ * dwc2_backup_host_registers() - Backup controller host registers.
+ * When suspending usb bus, registers needs to be backuped
+ * if controller power is disabled once suspended.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_hregs_backup *hr;
+ int i;
+
+ dev_dbg(hsotg->dev, "%s\n", __func__);
+
+ /* Backup Host regs */
+ hr = &hsotg->hr_backup;
+ hr->hcfg = DWC2_READ_4(hsotg, HCFG);
+ hr->haintmsk = DWC2_READ_4(hsotg, HAINTMSK);
+ for (i = 0; i < hsotg->core_params->host_channels; ++i)
+ hr->hcintmsk[i] = DWC2_READ_4(hsotg, HCINTMSK(i));
+
+ hr->hprt0 = DWC2_READ_4(hsotg, HPRT0);
+ hr->hfir = DWC2_READ_4(hsotg, HFIR);
+ hr->valid = true;
+
+ return 0;
+}
+
+/**
+ * dwc2_restore_host_registers() - Restore controller host registers.
+ * When resuming usb bus, device registers needs to be restored
+ * if controller power were disabled.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_hregs_backup *hr;
+ int i;
+
+ dev_dbg(hsotg->dev, "%s\n", __func__);
+
+ /* Restore host regs */
+ hr = &hsotg->hr_backup;
+ if (!hr->valid) {
+ dev_err(hsotg->dev, "%s: no host registers to restore\n",
+ __func__);
+ return -EINVAL;
+ }
+ hr->valid = false;
+
+ DWC2_WRITE_4(hsotg, HCFG, hr->hcfg);
+ DWC2_WRITE_4(hsotg, HAINTMSK, hr->haintmsk);
+
+ for (i = 0; i < hsotg->core_params->host_channels; ++i)
+ DWC2_WRITE_4(hsotg, HCINTMSK(i), hr->hcintmsk[i]);
+
+ DWC2_WRITE_4(hsotg, HPRT0, hr->hprt0);
+ DWC2_WRITE_4(hsotg, HFIR, hr->hfir);
+
+ return 0;
+}
+#else
+static inline int dwc2_backup_host_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+
+static inline int dwc2_restore_host_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+#endif
+
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+/**
+ * dwc2_backup_device_registers() - Backup controller device registers.
+ * When suspending usb bus, registers needs to be backuped
+ * if controller power is disabled once suspended.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_dregs_backup *dr;
+ int i;
+
+ dev_dbg(hsotg->dev, "%s\n", __func__);
+
+ /* Backup dev regs */
+ dr = &hsotg->dr_backup;
+
+ dr->dcfg = DWC2_READ_4(hsotg, DCFG);
+ dr->dctl = DWC2_READ_4(hsotg, DCTL);
+ dr->daintmsk = DWC2_READ_4(hsotg, DAINTMSK);
+ dr->diepmsk = DWC2_READ_4(hsotg, DIEPMSK);
+ dr->doepmsk = DWC2_READ_4(hsotg, DOEPMSK);
+
+ for (i = 0; i < hsotg->num_of_eps; i++) {
+ /* Backup IN EPs */
+ dr->diepctl[i] = DWC2_READ_4(hsotg, DIEPCTL(i));
+
+ /* Ensure DATA PID is correctly configured */
+ if (dr->diepctl[i] & DXEPCTL_DPID)
+ dr->diepctl[i] |= DXEPCTL_SETD1PID;
+ else
+ dr->diepctl[i] |= DXEPCTL_SETD0PID;
+
+ dr->dieptsiz[i] = DWC2_READ_4(hsotg, DIEPTSIZ(i));
+ dr->diepdma[i] = DWC2_READ_4(hsotg, DIEPDMA(i));
+
+ /* Backup OUT EPs */
+ dr->doepctl[i] = DWC2_READ_4(hsotg, DOEPCTL(i));
+
+ /* Ensure DATA PID is correctly configured */
+ if (dr->doepctl[i] & DXEPCTL_DPID)
+ dr->doepctl[i] |= DXEPCTL_SETD1PID;
+ else
+ dr->doepctl[i] |= DXEPCTL_SETD0PID;
+
+ dr->doeptsiz[i] = DWC2_READ_4(hsotg, DOEPTSIZ(i));
+ dr->doepdma[i] = DWC2_READ_4(hsotg, DOEPDMA(i));
+ }
+ dr->valid = true;
+ return 0;
+}
+
+/**
+ * dwc2_restore_device_registers() - Restore controller device registers.
+ * When resuming usb bus, device registers needs to be restored
+ * if controller power were disabled.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_dregs_backup *dr;
+ u32 dctl;
+ int i;
+
+ dev_dbg(hsotg->dev, "%s\n", __func__);
+
+ /* Restore dev regs */
+ dr = &hsotg->dr_backup;
+ if (!dr->valid) {
+ dev_err(hsotg->dev, "%s: no device registers to restore\n",
+ __func__);
+ return -EINVAL;
+ }
+ dr->valid = false;
+
+ DWC2_WRITE_4(hsotg, DCFG, dr->dcfg);
+ DWC2_WRITE_4(hsotg, DCTL, dr->dctl);
+ DWC2_WRITE_4(hsotg, DAINTMSK, dr->daintmsk);
+ DWC2_WRITE_4(hsotg, DIEPMSK, dr->diepmsk);
+ DWC2_WRITE_4(hsotg, DOEPMSK, dr->doepmsk);
+
+ for (i = 0; i < hsotg->num_of_eps; i++) {
+ /* Restore IN EPs */
+ DWC2_WRITE_4(hsotg, DIEPCTL(i), dr->diepctl[i]);
+ DWC2_WRITE_4(hsotg, DIEPTSIZ(i), dr->dieptsiz[i]);
+ DWC2_WRITE_4(hsotg, DIEPDMA(i), dr->diepdma[i]);
+
+ /* Restore OUT EPs */
+ DWC2_WRITE_4(hsotg, DOEPCTL(i), dr->doepctl[i]);
+ DWC2_WRITE_4(hsotg, DOEPTSIZ(i), dr->doeptsiz[i]);
+ DWC2_WRITE_4(hsotg, DOEPDMA(i), dr->doepdma[i]);
+ }
+
+ /* Set the Power-On Programming done bit */
+ dctl = DWC2_READ_4(hsotg, DCTL);
+ dctl |= DCTL_PWRONPRGDONE;
+ DWC2_WRITE_4(hsotg, DCTL, dctl);
+
+ return 0;
+}
+#else
+static inline int dwc2_backup_device_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+
+static inline int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg)
+{ return 0; }
+#endif
+
+/**
+ * dwc2_backup_global_registers() - Backup global controller registers.
+ * When suspending usb bus, registers needs to be backuped
+ * if controller power is disabled once suspended.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_backup_global_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_gregs_backup *gr;
+ int i;
+
+ /* Backup global regs */
+ gr = &hsotg->gr_backup;
+
+ gr->gotgctl = DWC2_READ_4(hsotg, GOTGCTL);
+ gr->gintmsk = DWC2_READ_4(hsotg, GINTMSK);
+ gr->gahbcfg = DWC2_READ_4(hsotg, GAHBCFG);
+ gr->gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
+ gr->grxfsiz = DWC2_READ_4(hsotg, GRXFSIZ);
+ gr->gnptxfsiz = DWC2_READ_4(hsotg, GNPTXFSIZ);
+ gr->hptxfsiz = DWC2_READ_4(hsotg, HPTXFSIZ);
+ gr->gdfifocfg = DWC2_READ_4(hsotg, GDFIFOCFG);
+ for (i = 0; i < MAX_EPS_CHANNELS; i++)
+ gr->dtxfsiz[i] = DWC2_READ_4(hsotg, DPTXFSIZN(i));
+
+ gr->valid = true;
+ return 0;
+}
+
+/**
+ * dwc2_restore_global_registers() - Restore controller global registers.
+ * When resuming usb bus, device registers needs to be restored
+ * if controller power were disabled.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+static int dwc2_restore_global_registers(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_gregs_backup *gr;
+ int i;
+
+ dev_dbg(hsotg->dev, "%s\n", __func__);
+
+ /* Restore global regs */
+ gr = &hsotg->gr_backup;
+ if (!gr->valid) {
+ dev_err(hsotg->dev, "%s: no global registers to restore\n",
+ __func__);
+ return -EINVAL;
+ }
+ gr->valid = false;
+
+ DWC2_WRITE_4(hsotg, GINTSTS, 0xffffffff);
+ DWC2_WRITE_4(hsotg, GOTGCTL, gr->gotgctl);
+ DWC2_WRITE_4(hsotg, GINTMSK, gr->gintmsk);
+ DWC2_WRITE_4(hsotg, GUSBCFG, gr->gusbcfg);
+ DWC2_WRITE_4(hsotg, GAHBCFG, gr->gahbcfg);
+ DWC2_WRITE_4(hsotg, GRXFSIZ, gr->grxfsiz);
+ DWC2_WRITE_4(hsotg, GNPTXFSIZ, gr->gnptxfsiz);
+ DWC2_WRITE_4(hsotg, HPTXFSIZ, gr->hptxfsiz);
+ DWC2_WRITE_4(hsotg, GDFIFOCFG, gr->gdfifocfg);
+ for (i = 0; i < MAX_EPS_CHANNELS; i++)
+ DWC2_WRITE_4(hsotg, DPTXFSIZN(i), gr->dtxfsiz[i]);
+
+ return 0;
+}
+
+/**
+ * dwc2_exit_hibernation() - Exit controller from Partial Power Down.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ * @restore: Controller registers need to be restored
+ */
+int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore)
+{
+ u32 pcgcctl;
+ int ret = 0;
+
+ if (!hsotg->core_params->hibernation)
+ return -ENOTSUPP;
+
+ pcgcctl = DWC2_READ_4(hsotg, PCGCTL);
+ pcgcctl &= ~PCGCTL_STOPPCLK;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+
+ pcgcctl = DWC2_READ_4(hsotg, PCGCTL);
+ pcgcctl &= ~PCGCTL_PWRCLMP;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+
+ pcgcctl = DWC2_READ_4(hsotg, PCGCTL);
+ pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+
+ udelay(100);
+ if (restore) {
+ ret = dwc2_restore_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore registers\n",
+ __func__);
+ return ret;
+ }
+ if (dwc2_is_host_mode(hsotg)) {
+ ret = dwc2_restore_host_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore host registers\n",
+ __func__);
+ return ret;
+ }
+ } else {
+ ret = dwc2_restore_device_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to restore device registers\n",
+ __func__);
+ return ret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * dwc2_enter_hibernation() - Put controller in Partial Power Down.
+ *
+ * @hsotg: Programming view of the DWC_otg controller
+ */
+int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
+{
+ u32 pcgcctl;
+ int ret = 0;
+
+ if (!hsotg->core_params->hibernation)
+ return -ENOTSUPP;
+
+ /* Backup all registers */
+ ret = dwc2_backup_global_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup global registers\n",
+ __func__);
+ return ret;
+ }
+
+ if (dwc2_is_host_mode(hsotg)) {
+ ret = dwc2_backup_host_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup host registers\n",
+ __func__);
+ return ret;
+ }
+ } else {
+ ret = dwc2_backup_device_registers(hsotg);
+ if (ret) {
+ dev_err(hsotg->dev, "%s: failed to backup device registers\n",
+ __func__);
+ return ret;
+ }
+ }
+
+ /* Put the controller in low power state */
+ pcgcctl = DWC2_READ_4(hsotg, PCGCTL);
+
+ pcgcctl |= PCGCTL_PWRCLMP;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+ ndelay(20);
+
+ pcgcctl |= PCGCTL_RSTPDWNMODULE;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+ ndelay(20);
+
+ pcgcctl |= PCGCTL_STOPPCLK;
+ DWC2_WRITE_4(hsotg, PCGCTL, pcgcctl);
+
+ return ret;
+}
+
/**
* dwc2_enable_common_interrupts() - Initializes the commmon interrupts,
* used in both device and host modes
@@ -88,8 +446,10 @@ static void dwc2_enable_common_interrupt
if (hsotg->core_params->dma_enable <= 0)
intmsk |= GINTSTS_RXFLVL;
+ if (hsotg->core_params->external_id_pin_ctl <= 0)
+ intmsk |= GINTSTS_CONIDSTSCHNG;
- intmsk |= GINTSTS_CONIDSTSCHNG | GINTSTS_WKUPINT | GINTSTS_USBSUSP |
+ intmsk |= GINTSTS_WKUPINT | GINTSTS_USBSUSP |
GINTSTS_SESSREQINT;
DWC2_WRITE_4(hsotg, GINTMSK, intmsk);
@@ -129,6 +489,7 @@ static int dwc2_core_reset(struct dwc2_h
{
u32 greset;
int count = 0;
+ u32 gusbcfg;
dev_vdbg(hsotg->dev, "%s()\n", __func__);
@@ -159,6 +520,23 @@ static int dwc2_core_reset(struct dwc2_h
}
} while (greset & GRSTCTL_CSFTRST);
+ if (hsotg->dr_mode == USB_DR_MODE_HOST) {
+ gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
+ gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
+ gusbcfg |= GUSBCFG_FORCEHOSTMODE;
+ DWC2_WRITE_4(hsotg, GUSBCFG, gusbcfg);
+ } else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL) {
+ gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
+ gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
+ gusbcfg |= GUSBCFG_FORCEDEVMODE;
+ DWC2_WRITE_4(hsotg, GUSBCFG, gusbcfg);
+ } else if (hsotg->dr_mode == USB_DR_MODE_OTG) {
+ gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
+ gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
+ gusbcfg &= ~GUSBCFG_FORCEDEVMODE;
+ DWC2_WRITE_4(hsotg, GUSBCFG, gusbcfg);
+ }
+
/*
* NOTE: This long sleep is _very_ important, otherwise the core will
* not stay in host mode after a connector ID change!
@@ -312,13 +690,8 @@ static int dwc2_gahbcfg_init(struct dwc2
switch (hsotg->hw_params.arch) {
case GHWCFG2_EXT_DMA_ARCH:
- dev_dbg(hsotg->dev, "External DMA Mode\n");
- if (hsotg->core_params->ahbcfg != -1) {
- ahbcfg &= GAHBCFG_CTRL_MASK;
- ahbcfg |= hsotg->core_params->ahbcfg &
- ~GAHBCFG_CTRL_MASK;
- }
- break;
+ dev_err(hsotg->dev, "External DMA Mode not supported\n");
+ return -EINVAL;
case GHWCFG2_INT_DMA_ARCH:
dev_dbg(hsotg->dev, "Internal DMA Mode\n");
@@ -460,7 +833,7 @@ int dwc2_core_init(struct dwc2_hsotg *hs
dwc2_enable_common_interrupts(hsotg);
/*
- * Do device or host intialization based on mode during PCD and
+ * Do device or host initialization based on mode during PCD and
* HCD initialization
*/
if (dwc2_is_host_mode(hsotg)) {
@@ -513,6 +886,72 @@ void dwc2_disable_host_interrupts(struct
DWC2_WRITE_4(hsotg, GINTMSK, intmsk);
}
+/*
+ * dwc2_calculate_dynamic_fifo() - Calculates the default fifo size
+ * For system that have a total fifo depth that is smaller than the default
+ * RX + TX fifo size.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ */
+static void dwc2_calculate_dynamic_fifo(struct dwc2_hsotg *hsotg)
+{
+ struct dwc2_core_params *params = hsotg->core_params;
+ struct dwc2_hw_params *hw = &hsotg->hw_params;
+ u32 rxfsiz, nptxfsiz, ptxfsiz, total_fifo_size;
+
+ total_fifo_size = hw->total_fifo_size;
+ rxfsiz = params->host_rx_fifo_size;
+ nptxfsiz = params->host_nperio_tx_fifo_size;
+ ptxfsiz = params->host_perio_tx_fifo_size;
+
+ /*
+ * Will use Method 2 defined in the DWC2 spec: minimum FIFO depth
+ * allocation with support for high bandwidth endpoints. Synopsys
+ * defines MPS(Max Packet size) for a periodic EP=1024, and for
+ * non-periodic as 512.
+ */
+ if (total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)) {
+ /*
+ * For Buffer DMA mode/Scatter Gather DMA mode
+ * 2 * ((Largest Packet size / 4) + 1 + 1) + n
+ * with n = number of host channel.
+ * 2 * ((1024/4) + 2) = 516
+ */
+ rxfsiz = 516 + hw->host_channels;
+
+ /*
+ * min non-periodic tx fifo depth
+ * 2 * (largest non-periodic USB packet used / 4)
+ * 2 * (512/4) = 256
+ */
+ nptxfsiz = 256;
+
+ /*
+ * min periodic tx fifo depth
+ * (largest packet size*MC)/4
+ * (1024 * 3)/4 = 768
+ */
+ ptxfsiz = 768;
+
+ params->host_rx_fifo_size = rxfsiz;
+ params->host_nperio_tx_fifo_size = nptxfsiz;
+ params->host_perio_tx_fifo_size = ptxfsiz;
+ }
+
+ /*
+ * If the summation of RX, NPTX and PTX fifo sizes is still
+ * bigger than the total_fifo_size, then we have a problem.
+ *
+ * We won't be able to allocate as many endpoints. Right now,
+ * we're just printing an error message, but ideally this FIFO
+ * allocation algorithm would be improved in the future.
+ *
+ * FIXME improve this FIFO allocation algorithm.
+ */
+ if (unlikely(total_fifo_size < (rxfsiz + nptxfsiz + ptxfsiz)))
+ dev_err(hsotg->dev, "invalid fifo sizes\n");
+}
+
static void dwc2_config_fifos(struct dwc2_hsotg *hsotg)
{
struct dwc2_core_params *params = hsotg->core_params;
@@ -521,6 +960,8 @@ static void dwc2_config_fifos(struct dwc
if (!params->enable_dynamic_fifo)
return;
+ dwc2_calculate_dynamic_fifo(hsotg);
+
/* Rx FIFO */
grxfsiz = DWC2_READ_4(hsotg, GRXFSIZ);
dev_dbg(hsotg->dev, "initial grxfsiz=%08x\n", grxfsiz);
@@ -1401,18 +1842,10 @@ void dwc2_hc_start_transfer(struct dwc2_
} else {
dma_addr = chan->xfer_dma;
}
- if (hsotg->hsotg_sc->sc_set_dma_addr == NULL) {
- DWC2_WRITE_4(hsotg, HCDMA(chan->hc_num),
- (u32)dma_addr);
- if (dbg_hc(chan))
- dev_vdbg(hsotg->dev,
- "Wrote %08lx to HCDMA(%d)\n",
- (unsigned long)dma_addr,
- chan->hc_num);
- } else {
- (void)(*hsotg->hsotg_sc->sc_set_dma_addr)(
- hsotg->dev, dma_addr, chan->hc_num);
- }
+ DWC2_WRITE_4(hsotg, HCDMA(chan->hc_num), (u32)dma_addr);
+ if (dbg_hc(chan))
+ dev_vdbg(hsotg->dev, "Wrote %08lx to HCDMA(%d)\n",
+ (unsigned long)dma_addr, chan->hc_num);
}
/* Start the split */
@@ -2539,6 +2972,40 @@ static void dwc2_set_param_uframe_sched(
hsotg->core_params->uframe_sched = val;
}
+static void dwc2_set_param_external_id_pin_ctl(struct dwc2_hsotg *hsotg,
+ int val)
+{
+ if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
+ if (val >= 0) {
+ dev_err(hsotg->dev,
+ "'%d' invalid for parameter external_id_pin_ctl\n",
+ val);
+ dev_err(hsotg->dev, "external_id_pin_ctl must be 0 or 1\n");
+ }
+ val = 0;
+ dev_dbg(hsotg->dev, "Setting external_id_pin_ctl to %d\n", val);
+ }
+
+ hsotg->core_params->external_id_pin_ctl = val;
+}
+
+static void dwc2_set_param_hibernation(struct dwc2_hsotg *hsotg,
+ int val)
+{
+ if (DWC2_OUT_OF_BOUNDS(val, 0, 1)) {
+ if (val >= 0) {
+ dev_err(hsotg->dev,
+ "'%d' invalid for parameter hibernation\n",
+ val);
+ dev_err(hsotg->dev, "hibernation must be 0 or 1\n");
+ }
+ val = 0;
+ dev_dbg(hsotg->dev, "Setting hibernation to %d\n", val);
+ }
+
+ hsotg->core_params->hibernation = val;
+}
+
/*
* This function is called during module intialization to pass module parameters
* for the DWC_otg core.
@@ -2583,6 +3050,8 @@ void dwc2_set_parameters(struct dwc2_hso
dwc2_set_param_ahbcfg(hsotg, params->ahbcfg);
dwc2_set_param_otg_ver(hsotg, params->otg_ver);
dwc2_set_param_uframe_sched(hsotg, params->uframe_sched);
+ dwc2_set_param_external_id_pin_ctl(hsotg, params->external_id_pin_ctl);
+ dwc2_set_param_hibernation(hsotg, params->hibernation);
}
/**
@@ -2618,23 +3087,23 @@ int dwc2_get_hwparams(struct dwc2_hsotg
hwcfg2 = DWC2_READ_4(hsotg, GHWCFG2);
hwcfg3 = DWC2_READ_4(hsotg, GHWCFG3);
hwcfg4 = DWC2_READ_4(hsotg, GHWCFG4);
- gnptxfsiz = DWC2_READ_4(hsotg, GNPTXFSIZ);
grxfsiz = DWC2_READ_4(hsotg, GRXFSIZ);
dev_dbg(hsotg->dev, "hwcfg1=%08x\n", DWC2_READ_4(hsotg, GHWCFG1));
dev_dbg(hsotg->dev, "hwcfg2=%08x\n", hwcfg2);
dev_dbg(hsotg->dev, "hwcfg3=%08x\n", hwcfg3);
dev_dbg(hsotg->dev, "hwcfg4=%08x\n", hwcfg4);
- dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
dev_dbg(hsotg->dev, "grxfsiz=%08x\n", grxfsiz);
- /* Force host mode to get HPTXFSIZ exact power on value */
+ /* Force host mode to get HPTXFSIZ / GNPTXFSIZ exact power on value */
gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
gusbcfg |= GUSBCFG_FORCEHOSTMODE;
DWC2_WRITE_4(hsotg, GUSBCFG, gusbcfg);
usleep_range(100000, 150000);
+ gnptxfsiz = DWC2_READ_4(hsotg, GNPTXFSIZ);
hptxfsiz = DWC2_READ_4(hsotg, HPTXFSIZ);
+ dev_dbg(hsotg->dev, "gnptxfsiz=%08x\n", gnptxfsiz);
dev_dbg(hsotg->dev, "hptxfsiz=%08x\n", hptxfsiz);
gusbcfg = DWC2_READ_4(hsotg, GUSBCFG);
gusbcfg &= ~GUSBCFG_FORCEHOSTMODE;
@@ -2669,6 +3138,13 @@ int dwc2_get_hwparams(struct dwc2_hsotg
width = (hwcfg3 & GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT;
hw->max_transfer_size = (1 << (width + 11)) - 1;
+ /*
+ * Clip max_transfer_size to 65535. dwc2_hc_setup_align_buf() allocates
+ * coherent buffers with this size, and if it's too large we can
+ * exhaust the coherent DMA pool.
+ */
+ if (hw->max_transfer_size > 65535)
+ hw->max_transfer_size = 65535;
width = (hwcfg3 & GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK) >>
GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT;
hw->max_packet_count = (1 << (width + 4)) - 1;
@@ -2743,6 +3219,22 @@ int dwc2_get_hwparams(struct dwc2_hsotg
return 0;
}
+/*
+ * Sets all parameters to the given value.
+ *
+ * Assumes that the dwc2_core_params struct contains only integers.
+ */
+void dwc2_set_all_params(struct dwc2_core_params *params, int value)
+{
+ int *p = (int *)params;
+ size_t size = sizeof(*params) / sizeof(*p);
+ int i;
+
+ for (i = 0; i < size; i++)
+ p[i] = value;
+}
+
+
u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg)
{
return hsotg->core_params->otg_ver == 1 ? 0x0200 : 0x0103;
Index: src/sys/external/bsd/dwc2/dist/dwc2_core.h
diff -u src/sys/external/bsd/dwc2/dist/dwc2_core.h:1.5 src/sys/external/bsd/dwc2/dist/dwc2_core.h:1.6
--- src/sys/external/bsd/dwc2/dist/dwc2_core.h:1.5 Thu Apr 3 06:34:58 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_core.h Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_core.h,v 1.5 2014/04/03 06:34:58 skrll Exp $ */
+/* $NetBSD: dwc2_core.h,v 1.6 2015/08/30 12:59:59 skrll Exp $ */
/*
* core.h - DesignWare HS OTG Controller common declarations
@@ -53,6 +53,129 @@
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+
+/* s3c-hsotg declarations */
+static const char * const s3c_hsotg_supply_names[] = {
+ "vusb_d", /* digital USB supply, 1.2V */
+ "vusb_a", /* analog USB supply, 1.1V */
+};
+
+/*
+ * EP0_MPS_LIMIT
+ *
+ * Unfortunately there seems to be a limit of the amount of data that can
+ * be transferred by IN transactions on EP0. This is either 127 bytes or 3
+ * packets (which practically means 1 packet and 63 bytes of data) when the
+ * MPS is set to 64.
+ *
+ * This means if we are wanting to move >127 bytes of data, we need to
+ * split the transactions up, but just doing one packet at a time does
+ * not work (this may be an implicit DATA0 PID on first packet of the
+ * transaction) and doing 2 packets is outside the controller's limits.
+ *
+ * If we try to lower the MPS size for EP0, then no transfers work properly
+ * for EP0, and the system will fail basic enumeration. As no cause for this
+ * has currently been found, we cannot support any large IN transfers for
+ * EP0.
+ */
+#define EP0_MPS_LIMIT 64
+
+struct dwc2_hsotg;
+struct s3c_hsotg_req;
+
+/**
+ * struct s3c_hsotg_ep - driver endpoint definition.
+ * @ep: The gadget layer representation of the endpoint.
+ * @name: The driver generated name for the endpoint.
+ * @queue: Queue of requests for this endpoint.
+ * @parent: Reference back to the parent device structure.
+ * @req: The current request that the endpoint is processing. This is
+ * used to indicate an request has been loaded onto the endpoint
+ * and has yet to be completed (maybe due to data move, or simply
+ * awaiting an ack from the core all the data has been completed).
+ * @debugfs: File entry for debugfs file for this endpoint.
+ * @lock: State lock to protect contents of endpoint.
+ * @dir_in: Set to true if this endpoint is of the IN direction, which
+ * means that it is sending data to the Host.
+ * @index: The index for the endpoint registers.
+ * @mc: Multi Count - number of transactions per microframe
+ * @interval - Interval for periodic endpoints
+ * @name: The name array passed to the USB core.
+ * @halted: Set if the endpoint has been halted.
+ * @periodic: Set if this is a periodic ep, such as Interrupt
+ * @isochronous: Set if this is a isochronous ep
+ * @send_zlp: Set if we need to send a zero-length packet.
+ * @total_data: The total number of data bytes done.
+ * @fifo_size: The size of the FIFO (for periodic IN endpoints)
+ * @fifo_load: The amount of data loaded into the FIFO (periodic IN)
+ * @last_load: The offset of data for the last start of request.
+ * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN
+ *
+ * This is the driver's state for each registered enpoint, allowing it
+ * to keep track of transactions that need doing. Each endpoint has a
+ * lock to protect the state, to try and avoid using an overall lock
+ * for the host controller as much as possible.
+ *
+ * For periodic IN endpoints, we have fifo_size and fifo_load to try
+ * and keep track of the amount of data in the periodic FIFO for each
+ * of these as we don't have a status register that tells us how much
+ * is in each of them. (note, this may actually be useless information
+ * as in shared-fifo mode periodic in acts like a single-frame packet
+ * buffer than a fifo)
+ */
+struct s3c_hsotg_ep {
+ struct usb_ep ep;
+ struct list_head queue;
+ struct dwc2_hsotg *parent;
+ struct s3c_hsotg_req *req;
+ struct dentry *debugfs;
+
+ unsigned long total_data;
+ unsigned int size_loaded;
+ unsigned int last_load;
+ unsigned int fifo_load;
+ unsigned short fifo_size;
+ unsigned short fifo_index;
+
+ unsigned char dir_in;
+ unsigned char index;
+ unsigned char mc;
+ unsigned char interval;
+
+ unsigned int halted:1;
+ unsigned int periodic:1;
+ unsigned int isochronous:1;
+ unsigned int send_zlp:1;
+
+ char name[10];
+};
+
+/**
+ * struct s3c_hsotg_req - data transfer request
+ * @req: The USB gadget request
+ * @queue: The list of requests for the endpoint this is queued for.
+ * @saved_req_buf: variable to save req.buf when bounce buffers are used.
+ */
+struct s3c_hsotg_req {
+ struct usb_request req;
+ struct list_head queue;
+ void *saved_req_buf;
+};
+
+#define call_gadget(_hs, _entry) \
+do { \
+ if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \
+ (_hs)->driver && (_hs)->driver->_entry) { \
+ spin_unlock(&_hs->lock); \
+ (_hs)->driver->_entry(&(_hs)->gadget); \
+ spin_lock(&_hs->lock); \
+ } \
+} while (0)
+#else
+#define call_gadget(_hs, _entry) do {} while (0)
+#endif
+
struct dwc2_hsotg;
struct dwc2_host_chan;
@@ -64,6 +187,22 @@ enum dwc2_lx_state {
DWC2_L3, /* Off state */
};
+/*
+ * Gadget periodic tx fifo sizes as used by legacy driver
+ * EP0 is not included
+ */
+#define DWC2_G_P_LEGACY_TX_FIFO_SIZE {256, 256, 256, 256, 768, 768, 768, \
+ 768, 0, 0, 0, 0, 0, 0, 0}
+
+/* Gadget ep0 states */
+enum dwc2_ep0_state {
+ DWC2_EP0_SETUP,
+ DWC2_EP0_DATA_IN,
+ DWC2_EP0_DATA_OUT,
+ DWC2_EP0_STATUS_IN,
+ DWC2_EP0_STATUS_OUT,
+};
+
/**
* struct dwc2_core_params - Parameters for configuring the core
*
@@ -188,6 +327,17 @@ enum dwc2_lx_state {
* by the driver and are ignored in this
* configuration value.
* @uframe_sched: True to enable the microframe scheduler
+ * @external_id_pin_ctl: Specifies whether ID pin is handled externally.
+ * Disable CONIDSTSCHNG controller interrupt in such
+ * case.
+ * 0 - No (default)
+ * 1 - Yes
+ * @hibernation: Specifies whether the controller support hibernation.
+ * If hibernation is enabled, the controller will enter
+ * hibernation in both peripheral and host mode when
+ * needed.
+ * 0 - No (default)
+ * 1 - Yes
*
* The following parameters may be specified when starting the module. These
* parameters define how the DWC_otg controller should be configured. A
@@ -225,6 +375,8 @@ struct dwc2_core_params {
int reload_ctl;
int ahbcfg;
int uframe_sched;
+ int external_id_pin_ctl;
+ int hibernation;
};
/**
@@ -252,7 +404,7 @@ struct dwc2_core_params {
* @power_optimized Are power optimizations enabled?
* @num_dev_ep Number of device endpoints available
* @num_dev_perio_in_ep Number of device periodic IN endpoints
- * avaialable
+ * available
* @dev_token_q_depth Device Mode IN Token Sequence Learning Queue
* Depth
* 0 to 30
@@ -305,19 +457,109 @@ struct dwc2_hw_params {
u32 snpsid;
};
+/* Size of control and EP0 buffers */
+#define DWC2_CTRL_BUFF_SIZE 8
+
+/**
+ * struct dwc2_gregs_backup - Holds global registers state before entering partial
+ * power down
+ * @gotgctl: Backup of GOTGCTL register
+ * @gintmsk: Backup of GINTMSK register
+ * @gahbcfg: Backup of GAHBCFG register
+ * @gusbcfg: Backup of GUSBCFG register
+ * @grxfsiz: Backup of GRXFSIZ register
+ * @gnptxfsiz: Backup of GNPTXFSIZ register
+ * @gi2cctl: Backup of GI2CCTL register
+ * @hptxfsiz: Backup of HPTXFSIZ register
+ * @gdfifocfg: Backup of GDFIFOCFG register
+ * @dtxfsiz: Backup of DTXFSIZ registers for each endpoint
+ * @gpwrdn: Backup of GPWRDN register
+ */
+struct dwc2_gregs_backup {
+ u32 gotgctl;
+ u32 gintmsk;
+ u32 gahbcfg;
+ u32 gusbcfg;
+ u32 grxfsiz;
+ u32 gnptxfsiz;
+ u32 gi2cctl;
+ u32 hptxfsiz;
+ u32 pcgcctl;
+ u32 gdfifocfg;
+ u32 dtxfsiz[MAX_EPS_CHANNELS];
+ u32 gpwrdn;
+ bool valid;
+};
+
+/**
+ * struct dwc2_dregs_backup - Holds device registers state before entering partial
+ * power down
+ * @dcfg: Backup of DCFG register
+ * @dctl: Backup of DCTL register
+ * @daintmsk: Backup of DAINTMSK register
+ * @diepmsk: Backup of DIEPMSK register
+ * @doepmsk: Backup of DOEPMSK register
+ * @diepctl: Backup of DIEPCTL register
+ * @dieptsiz: Backup of DIEPTSIZ register
+ * @diepdma: Backup of DIEPDMA register
+ * @doepctl: Backup of DOEPCTL register
+ * @doeptsiz: Backup of DOEPTSIZ register
+ * @doepdma: Backup of DOEPDMA register
+ */
+struct dwc2_dregs_backup {
+ u32 dcfg;
+ u32 dctl;
+ u32 daintmsk;
+ u32 diepmsk;
+ u32 doepmsk;
+ u32 diepctl[MAX_EPS_CHANNELS];
+ u32 dieptsiz[MAX_EPS_CHANNELS];
+ u32 diepdma[MAX_EPS_CHANNELS];
+ u32 doepctl[MAX_EPS_CHANNELS];
+ u32 doeptsiz[MAX_EPS_CHANNELS];
+ u32 doepdma[MAX_EPS_CHANNELS];
+ bool valid;
+};
+
+/**
+ * struct dwc2_hregs_backup - Holds host registers state before entering partial
+ * power down
+ * @hcfg: Backup of HCFG register
+ * @haintmsk: Backup of HAINTMSK register
+ * @hcintmsk: Backup of HCINTMSK register
+ * @hptr0: Backup of HPTR0 register
+ * @hfir: Backup of HFIR register
+ */
+struct dwc2_hregs_backup {
+ u32 hcfg;
+ u32 haintmsk;
+ u32 hcintmsk[MAX_EPS_CHANNELS];
+ u32 hprt0;
+ u32 hfir;
+ bool valid;
+};
+
/**
* struct dwc2_hsotg - Holds the state of the driver, including the non-periodic
* and periodic schedules
*
+ * These are common for both host and peripheral modes:
+ *
* @dev: The struct device pointer
* @regs: Pointer to controller regs
- * @core_params: Parameters that define how the core should be configured
* @hw_params: Parameters that were autodetected from the
* hardware registers
+ * @core_params: Parameters that define how the core should be configured
* @op_state: The operational State, during transitions (a_host=>
* a_peripheral and b_device=>b_host) this may not match
* the core, but allows the software to determine
* transitions
+ * @dr_mode: Requested mode of operation, one of following:
+ * - USB_DR_MODE_PERIPHERAL
+ * - USB_DR_MODE_HOST
+ * - USB_DR_MODE_OTG
+ * @lock: Spinlock that protects all the driver data structures
+ * @priv: Stores a pointer to the struct usb_hcd
* @queuing_high_bandwidth: True if multiple packets of a high-bandwidth
* transfer are in process of being queued
* @srp_success: Stores status of SRP request in the case of a FS PHY
@@ -327,6 +569,12 @@ struct dwc2_hw_params {
* interrupt
* @wkp_timer: Timer object for handling Wakeup Detected interrupt
* @lx_state: Lx state of connected device
+ * @gregs_backup: Backup of global registers during suspend
+ * @dregs_backup: Backup of device registers during suspend
+ * @hregs_backup: Backup of host registers during suspend
+ *
+ * These are for host mode:
+ *
* @flags: Flags for handling root port state changes
* @non_periodic_sched_inactive: Inactive QHs in the non-periodic schedule.
* Transfers associated with these QHs are not currently
@@ -395,11 +643,37 @@ struct dwc2_hw_params {
* @status_buf_dma: DMA address for status_buf
* @start_work: Delayed work for handling host A-cable connection
* @reset_work: Delayed work for handling a port reset
- * @lock: Spinlock that protects all the driver data structures
- * @priv: Stores a pointer to the struct usb_hcd
* @otg_port: OTG port number
* @frame_list: Frame list
* @frame_list_dma: Frame list DMA address
+ *
+ * These are for peripheral mode:
+ *
+ * @driver: USB gadget driver
+ * @phy: The otg phy transceiver structure for phy control.
+ * @uphy: The otg phy transceiver structure for old USB phy control.
+ * @plat: The platform specific configuration data. This can be removed once
+ * all SoCs support usb transceiver.
+ * @supplies: Definition of USB power supplies
+ * @phyif: PHY interface width
+ * @dedicated_fifos: Set if the hardware has dedicated IN-EP fifos.
+ * @num_of_eps: Number of available EPs (excluding EP0)
+ * @debug_root: Root directrory for debugfs.
+ * @debug_file: Main status file for debugfs.
+ * @debug_testmode: Testmode status file for debugfs.
+ * @debug_fifo: FIFO status file for debugfs.
+ * @ep0_reply: Request used for ep0 reply.
+ * @ep0_buff: Buffer for EP0 reply data, if needed.
+ * @ctrl_buff: Buffer for EP0 control requests.
+ * @ctrl_req: Request for EP0 control packets.
+ * @ep0_state: EP0 control transfers state
+ * @test_mode: USB test mode requested by the host
+ * @last_rst: Time of last reset
+ * @eps: The endpoints being supplied to the gadget framework
+ * @g_using_dma: Indicate if dma usage is enabled
+ * @g_rx_fifo_sz: Contains rx fifo size value
+ * @g_np_g_tx_fifo_sz: Contains Non-Periodic tx fifo size value
+ * @g_tx_fifo_sz: Contains tx fifo size value per endpoints
*/
struct dwc2_hsotg {
device_t dev;
@@ -409,6 +683,21 @@ struct dwc2_hsotg {
/** Params to actually use */
struct dwc2_core_params *core_params;
enum usb_otg_state op_state;
+ enum usb_dr_mode dr_mode;
+ unsigned int hcd_enabled:1;
+ unsigned int gadget_enabled:1;
+
+ spinlock_t lock;
+ void *priv;
+ struct usb_phy *uphy;
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+ struct phy *phy;
+ struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsotg_supply_names)];
+
+ struct mutex init_mutex;
+ int irq;
+ struct clk *clk;
+#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
unsigned int queuing_high_bandwidth:1;
unsigned int srp_success:1;
@@ -417,7 +706,21 @@ struct dwc2_hsotg {
struct work wf_otg;
struct callout wkp_timer;
enum dwc2_lx_state lx_state;
+ struct dwc2_gregs_backup gr_backup;
+ struct dwc2_dregs_backup dr_backup;
+ struct dwc2_hregs_backup hr_backup;
+ struct dentry *debug_root;
+ struct debugfs_regset32 *regset;
+
+ /* DWC OTG HW Release versions */
+#define DWC2_CORE_REV_2_71a 0x4f54271a
+#define DWC2_CORE_REV_2_90a 0x4f54290a
+#define DWC2_CORE_REV_2_92a 0x4f54292a
+#define DWC2_CORE_REV_2_94a 0x4f54294a
+#define DWC2_CORE_REV_3_00a 0x4f54300a
+
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
union dwc2_hcd_internal_flags {
u32 d32;
struct {
@@ -428,7 +731,7 @@ struct dwc2_hsotg {
unsigned port_suspend_change:1;
unsigned port_over_current_change:1;
unsigned port_l1_change:1;
- unsigned reserved:26;
+ unsigned reserved:25;
} b;
} flags;
@@ -465,20 +768,11 @@ struct dwc2_hsotg {
struct delayed_work start_work;
struct delayed_work reset_work;
- spinlock_t lock;
- void *priv;
u8 otg_port;
usb_dma_t frame_list_usbdma;
u32 *frame_list;
dma_addr_t frame_list_dma;
- /* DWC OTG HW Release versions */
-#define DWC2_CORE_REV_2_71a 0x4f54271a
-#define DWC2_CORE_REV_2_90a 0x4f54290a
-#define DWC2_CORE_REV_2_92a 0x4f54292a
-#define DWC2_CORE_REV_2_94a 0x4f54294a
-#define DWC2_CORE_REV_3_00a 0x4f54300a
-
#ifdef DEBUG
u32 frrem_samples;
u64 frrem_accum;
@@ -497,6 +791,37 @@ struct dwc2_hsotg {
u32 hfnum_other_samples_b;
u64 hfnum_other_frrem_accum_b;
#endif
+#endif /* CONFIG_USB_DWC2_HOST || CONFIG_USB_DWC2_DUAL_ROLE */
+
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+ /* Gadget structures */
+ struct usb_gadget_driver *driver;
+ struct s3c_hsotg_plat *plat;
+
+ u32 phyif;
+ int fifo_mem;
+ unsigned int dedicated_fifos:1;
+ unsigned char num_of_eps;
+ u32 fifo_map;
+
+ struct usb_request *ep0_reply;
+ struct usb_request *ctrl_req;
+ void *ep0_buff;
+ void *ctrl_buff;
+ enum dwc2_ep0_state ep0_state;
+ u8 test_mode;
+
+ struct usb_gadget gadget;
+ unsigned int enabled:1;
+ unsigned int connected:1;
+ unsigned long last_rst;
+ struct s3c_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
+ struct s3c_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
+ u32 g_using_dma;
+ u32 g_rx_fifo_sz;
+ u32 g_np_g_tx_fifo_sz;
+ u32 g_tx_fifo_sz[MAX_EPS_CHANNELS];
+#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
};
/* Reasons for halting a host channel */
@@ -522,6 +847,8 @@ enum dwc2_halt_status {
* and the DWC_otg controller
*/
extern void dwc2_core_host_init(struct dwc2_hsotg *hsotg);
+extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
+extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
/*
* Host core Functions.
@@ -754,6 +1081,15 @@ extern void dwc2_set_param_ahbcfg(struct
extern void dwc2_set_param_otg_ver(struct dwc2_hsotg *hsotg, int val);
+extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
+ const struct dwc2_core_params *params);
+
+extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
+
+extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
+
+
+
/*
* Dump core registers and SPRAM
*/
@@ -766,4 +1102,49 @@ extern void dwc2_dump_global_registers(s
*/
extern u16 dwc2_get_otg_version(struct dwc2_hsotg *hsotg);
+/* Gadget defines */
+#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+extern int s3c_hsotg_remove(struct dwc2_hsotg *hsotg);
+extern int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2);
+extern int s3c_hsotg_resume(struct dwc2_hsotg *dwc2);
+extern int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq);
+extern void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+ bool reset);
+extern void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg);
+extern void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2);
+extern int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg, int testmode);
+#define dwc2_is_device_connected(hsotg) (hsotg->connected)
+#else
+static inline int s3c_hsotg_remove(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int s3c_hsotg_suspend(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int s3c_hsotg_resume(struct dwc2_hsotg *dwc2)
+{ return 0; }
+static inline int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
+{ return 0; }
+static inline void s3c_hsotg_core_init_disconnected(struct dwc2_hsotg *dwc2,
+ bool reset) {}
+static inline void s3c_hsotg_core_connect(struct dwc2_hsotg *hsotg) {}
+static inline void s3c_hsotg_disconnect(struct dwc2_hsotg *dwc2) {}
+static inline int s3c_hsotg_set_test_mode(struct dwc2_hsotg *hsotg,
+ int testmode)
+{ return 0; }
+#define dwc2_is_device_connected(hsotg) (0)
+#endif
+
+#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
+extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
+#else
+static inline int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg)
+{ return 0; }
+static inline void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hcd_start(struct dwc2_hsotg *hsotg) {}
+static inline void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) {}
+static inline int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
+{ return 0; }
+#endif
+
#endif /* __DWC2_CORE_H__ */
Index: src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c
diff -u src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c:1.8 src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c:1.9
--- src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c:1.8 Fri Apr 4 05:40:57 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_coreintr.c Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_coreintr.c,v 1.8 2014/04/04 05:40:57 skrll Exp $ */
+/* $NetBSD: dwc2_coreintr.c,v 1.9 2015/08/30 12:59:59 skrll Exp $ */
/*
* core_intr.c - DesignWare HS OTG Controller common interrupt handling
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_coreintr.c,v 1.8 2014/04/04 05:40:57 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_coreintr.c,v 1.9 2015/08/30 12:59:59 skrll Exp $");
#include <sys/param.h>
#include <sys/kernel.h>
@@ -57,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2_coreint
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/err.h>
#include <dwc2/dwc2.h>
#include <dwc2/dwc2var.h>
@@ -141,6 +142,9 @@ static void dwc2_handle_otg_intr(struct
dwc2_op_state_str(hsotg));
gotgctl = DWC2_READ_4(hsotg, GOTGCTL);
+ if (dwc2_is_device_mode(hsotg))
+ s3c_hsotg_disconnect(hsotg);
+
if (hsotg->op_state == OTG_STATE_B_HOST) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
} else {
@@ -300,9 +304,11 @@ static void dwc2_handle_conn_id_status_c
* Release lock before scheduling workq as it holds spinlock during
* scheduling.
*/
- spin_unlock(&hsotg->lock);
- workqueue_enqueue(hsotg->wq_otg, &hsotg->wf_otg, NULL);
- spin_lock(&hsotg->lock);
+ if (hsotg->wq_otg) {
+ spin_unlock(&hsotg->lock);
+ workqueue_enqueue(hsotg->wq_otg, &hsotg->wf_otg, NULL);
+ spin_lock(&hsotg->lock);
+ }
/* Clear interrupt */
DWC2_WRITE_4(hsotg, GINTSTS, GINTSTS_CONIDSTSCHNG);
@@ -325,6 +331,12 @@ static void dwc2_handle_session_req_intr
/* Clear interrupt */
DWC2_WRITE_4(hsotg, GINTSTS, GINTSTS_SESSREQINT);
+
+ /*
+ * Report disconnect if there is any previous session established
+ */
+ if (dwc2_is_device_mode(hsotg))
+ s3c_hsotg_disconnect(hsotg);
}
/*
@@ -336,6 +348,7 @@ static void dwc2_handle_session_req_intr
*/
static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
{
+ int ret;
dev_dbg(hsotg->dev, "++Resume or Remote Wakeup Detected Interrupt++\n");
dev_dbg(hsotg->dev, "%s lxstate = %d\n", __func__, hsotg->lx_state);
@@ -347,6 +360,11 @@ static void dwc2_handle_wakeup_detected_
/* Clear Remote Wakeup Signaling */
dctl &= ~DCTL_RMTWKUPSIG;
DWC2_WRITE_4(hsotg, DCTL, dctl);
+ ret = dwc2_exit_hibernation(hsotg, true);
+ if (ret && (ret != -ENOTSUPP))
+ dev_err(hsotg->dev, "exit hibernation failed\n");
+
+ call_gadget(hsotg, resume);
}
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
@@ -379,6 +397,9 @@ static void dwc2_handle_disconnect_intr(
dwc2_is_host_mode(hsotg) ? "Host" : "Device",
dwc2_op_state_str(hsotg));
+ if (hsotg->op_state == OTG_STATE_A_HOST)
+ dwc2_hcd_disconnect(hsotg);
+
/* Change to L3 (OFF) state */
hsotg->lx_state = DWC2_L3;
@@ -395,12 +416,12 @@ static void dwc2_handle_disconnect_intr(
*/
static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
{
+ u32 dsts;
+ int ret;
+
dev_dbg(hsotg->dev, "USB SUSPEND\n");
if (dwc2_is_device_mode(hsotg)) {
-#ifdef DWC2_DEBUG
- u32 dsts;
-
/*
* Check the Device status register to determine if the Suspend
* state is active
@@ -411,11 +432,43 @@ static void dwc2_handle_usb_suspend_intr
"DSTS.Suspend Status=%d HWCFG4.Power Optimize=%d\n",
!!(dsts & DSTS_SUSPSTS),
hsotg->hw_params.power_optimized);
-#endif
+ if ((dsts & DSTS_SUSPSTS) && hsotg->hw_params.power_optimized) {
+ /* Ignore suspend request before enumeration */
+ if (!dwc2_is_device_connected(hsotg)) {
+ dev_dbg(hsotg->dev,
+ "ignore suspend request before enumeration\n");
+ goto clear_int;
+ }
+
+ ret = dwc2_enter_hibernation(hsotg);
+ if (ret) {
+ if (ret != -ENOTSUPP)
+ dev_err(hsotg->dev,
+ "enter hibernation failed\n");
+ goto skip_power_saving;
+ }
+
+ udelay(100);
+
+ /* Ask phy to be suspended */
+ if (!IS_ERR_OR_NULL(hsotg->uphy))
+ usb_phy_set_suspend(hsotg->uphy, true);
+skip_power_saving:
+ /*
+ * Change to L2 (suspend) state before releasing
+ * spinlock
+ */
+ hsotg->lx_state = DWC2_L2;
+
+ /* Call gadget suspend callback */
+ call_gadget(hsotg, suspend);
+ }
} else {
if (hsotg->op_state == OTG_STATE_A_PERIPHERAL) {
dev_dbg(hsotg->dev, "a_peripheral->a_host\n");
+ /* Change to L2 (suspend) state */
+ hsotg->lx_state = DWC2_L2;
/* Clear the a_peripheral flag, back to a_host */
spin_unlock(&hsotg->lock);
dwc2_hcd_start(hsotg);
@@ -424,9 +477,7 @@ static void dwc2_handle_usb_suspend_intr
}
}
- /* Change to L2 (suspend) state */
- hsotg->lx_state = DWC2_L2;
-
+clear_int:
/* Clear interrupt */
DWC2_WRITE_4(hsotg, GINTSTS, GINTSTS_USBSUSP);
}
Index: src/sys/external/bsd/dwc2/dist/dwc2_hcd.c
diff -u src/sys/external/bsd/dwc2/dist/dwc2_hcd.c:1.15 src/sys/external/bsd/dwc2/dist/dwc2_hcd.c:1.16
--- src/sys/external/bsd/dwc2/dist/dwc2_hcd.c:1.15 Mon Nov 24 10:14:14 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_hcd.c Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcd.c,v 1.15 2014/11/24 10:14:14 skrll Exp $ */
+/* $NetBSD: dwc2_hcd.c,v 1.16 2015/08/30 12:59:59 skrll Exp $ */
/*
* hcd.c - DesignWare HS OTG Controller host-mode routines
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.15 2014/11/24 10:14:14 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v 1.16 2015/08/30 12:59:59 skrll Exp $");
#include <sys/types.h>
#include <sys/kmem.h>
@@ -57,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: dwc2_hcd.c,v
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/err.h>
#include <dwc2/dwc2.h>
#include <dwc2/dwc2var.h>
@@ -267,6 +268,14 @@ static void dwc2_hcd_cleanup_channels(st
*/
channel->qh = NULL;
}
+ /* All channels have been freed, mark them available */
+ if (hsotg->core_params->uframe_sched > 0) {
+ hsotg->available_host_channels =
+ hsotg->core_params->host_channels;
+ } else {
+ hsotg->non_periodic_channels = 0;
+ hsotg->periodic_channels = 0;
+ }
}
/**
@@ -328,10 +337,12 @@ void dwc2_hcd_disconnect(struct dwc2_hso
*/
static void dwc2_hcd_rem_wakeup(struct dwc2_hsotg *hsotg)
{
- if (hsotg->lx_state == DWC2_L2)
+ if (hsotg->lx_state == DWC2_L2) {
hsotg->flags.b.port_suspend_change = 1;
- else
+ usb_hcd_resume_root_hub(hsotg->priv);
+ } else {
hsotg->flags.b.port_l1_change = 1;
+ }
dwc2_root_intr(hsotg->hsotg_sc);
}
@@ -361,12 +372,11 @@ void dwc2_hcd_stop(struct dwc2_hsotg *hs
DWC2_WRITE_4(hsotg, HPRT0, 0);
}
-int
-dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg, struct dwc2_hcd_urb *urb,
- void **ep_handle, gfp_t mem_flags)
+/* Caller must hold driver lock */
+int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
+ struct dwc2_hcd_urb *urb, struct dwc2_qh *qh,
+ struct dwc2_qtd *qtd)
{
- struct dwc2_softc *sc = hsotg->hsotg_sc;
- struct dwc2_qtd *qtd;
u32 intr_mask;
int retval;
int dev_speed;
@@ -379,32 +389,28 @@ dwc2_hcd_urb_enqueue(struct dwc2_hsotg *
dev_speed = dwc2_host_get_speed(hsotg, urb->priv);
- /* Some core configurations cannot support LS traffic on a FS root port */
+ /* Some configurations cannot support LS traffic on a FS root port */
if ((dev_speed == USB_SPEED_LOW) &&
(hsotg->hw_params.fs_phy_type == GHWCFG2_FS_PHY_TYPE_DEDICATED) &&
(hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_UTMI)) {
u32 hprt0 = DWC2_READ_4(hsotg, HPRT0);
u32 prtspd = (hprt0 & HPRT0_SPD_MASK) >> HPRT0_SPD_SHIFT;
- if (prtspd == HPRT0_SPD_FULL_SPEED) {
+ if (prtspd == HPRT0_SPD_FULL_SPEED)
return -ENODEV;
- }
}
- qtd = pool_cache_get(sc->sc_qtdpool, PR_NOWAIT);
if (!qtd)
- return -ENOMEM;
+ return -EINVAL;
memset(qtd, 0, sizeof(*qtd));
dwc2_hcd_qtd_init(qtd, urb);
- retval = dwc2_hcd_qtd_add(hsotg, qtd, (struct dwc2_qh **)ep_handle,
- mem_flags);
+ retval = dwc2_hcd_qtd_add(hsotg, qtd, qh);
if (retval) {
dev_err(hsotg->dev,
"DWC OTG HCD URB Enqueue failed adding QTD. Error status %d\n",
retval);
- pool_cache_put(sc->sc_qtdpool, qtd);
return retval;
}
@@ -665,18 +671,20 @@ static void *dwc2_hc_init_xfer(struct dw
}
static int dwc2_hc_setup_align_buf(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
- struct dwc2_host_chan *chan, void *bufptr)
+ struct dwc2_host_chan *chan,
+ struct dwc2_hcd_urb *urb, void *bufptr)
{
u32 buf_size;
- if (chan->ep_type != USB_ENDPOINT_XFER_ISOC)
- buf_size = hsotg->core_params->max_transfer_size;
- else
- buf_size = 4096;
-
if (!qh->dw_align_buf) {
int err;
+ if (chan->ep_type != USB_ENDPOINT_XFER_ISOC)
+ buf_size = hsotg->core_params->max_transfer_size;
+ else
+ /* 3072 = 3 max-size Isoc packets */
+ buf_size = 3072;
+
qh->dw_align_buf = NULL;
qh->dw_align_buf_dma = 0;
err = usb_allocmem(&hsotg->hsotg_sc->sc_bus, buf_size, buf_size,
@@ -689,16 +697,26 @@ static int dwc2_hc_setup_align_buf(struc
}
if (!qh->dw_align_buf)
return -ENOMEM;
+ qh->dw_align_buf_size = buf_size;
}
- if (!chan->ep_is_in && chan->xfer_len) {
- usb_syncmem(chan->xfer_usbdma, 0, buf_size,
- BUS_DMASYNC_POSTWRITE);
- memcpy(qh->dw_align_buf, bufptr, chan->xfer_len);
- usb_syncmem(chan->xfer_usbdma, 0, buf_size,
- BUS_DMASYNC_PREWRITE);
+ if (chan->xfer_len) {
+ dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
+ void *usb_urb = urb->priv;
+
+ if (usb_urb) {
+ if (!chan->ep_is_in) {
+ memcpy(qh->dw_align_buf, bufptr,
+ chan->xfer_len);
+ }
+ } else {
+ dev_warn(hsotg->dev, "no URB in dwc2_urb\n");
+ }
}
+ usb_syncmem(&qh->dw_align_buf_usbdma, 0, qh->dw_align_buf_size,
+ chan->ep_is_in ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
+
chan->align_buf = qh->dw_align_buf_dma;
return 0;
}
@@ -793,8 +811,8 @@ static int dwc2_assign_and_init_hc(struc
/* Non DWORD-aligned buffer case */
if (bufptr) {
- dev_vdbg(hsotg->dev, "Non-aligned buffer%p\n", bufptr);
- if (dwc2_hc_setup_align_buf(hsotg, qh, chan, bufptr)) {
+ dev_vdbg(hsotg->dev, "Non-aligned buffer\n");
+ if (dwc2_hc_setup_align_buf(hsotg, qh, chan, urb, bufptr)) {
dev_err(hsotg->dev,
"%s: Failed to allocate memory to handle non-dword aligned buffer\n",
__func__);
@@ -1338,6 +1356,8 @@ dwc2_conn_id_status_change(struct work *
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false);
dwc2_enable_global_interrupts(hsotg);
+ s3c_hsotg_core_init_disconnected(hsotg, false);
+ s3c_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
dev_dbg(hsotg->dev, "connId A\n");
@@ -1485,7 +1505,7 @@ dwc2_hcd_hub_control(struct dwc2_hsotg *
hprt0 |= HPRT0_RES;
DWC2_WRITE_4(hsotg, HPRT0, hprt0);
hprt0 &= ~HPRT0_SUSP;
- usleep_range(100000, 150000);
+ msleep(USB_RESUME_TIMEOUT);
hprt0 &= ~HPRT0_RES;
DWC2_WRITE_4(hsotg, HPRT0, hprt0);
@@ -1566,9 +1586,10 @@ dwc2_hcd_hub_control(struct dwc2_hsotg *
dev_dbg(hsotg->dev, "GetHubDescriptor\n");
hub_desc = (usb_hub_descriptor_t *)buf;
hub_desc->bDescLength = 9;
- hub_desc->bDescriptorType = 0x29;
+ hub_desc->bDescriptorType = USB_DT_HUB;
hub_desc->bNbrPorts = 1;
- USETW(hub_desc->wHubCharacteristics, 0x08);
+ USETW(hub_desc->wHubCharacteristics, HUB_CHAR_COMMON_LPSM |
+ HUB_CHAR_INDV_PORT_OCPM);
hub_desc->bPwrOn2PwrGood = 1;
hub_desc->bHubContrCurrent = 0;
hub_desc->DeviceRemovable[0] = 0;
@@ -1727,6 +1748,15 @@ dwc2_hcd_hub_control(struct dwc2_hsotg *
/* Not supported */
break;
+ case USB_PORT_FEAT_TEST:
+ hprt0 = dwc2_read_hprt0(hsotg);
+ dev_dbg(hsotg->dev,
+ "SetPortFeature - USB_PORT_FEAT_TEST\n");
+ hprt0 &= ~HPRT0_TSTCTL_MASK;
+ hprt0 |= (windex >> 8) << HPRT0_TSTCTL_SHIFT;
+ DWC2_WRITE_4(hsotg, HPRT0, hprt0);
+ break;
+
default:
retval = -EINVAL;
dev_err(hsotg->dev,
@@ -2067,7 +2097,6 @@ dwc2_hcd_reset_func(struct work *work)
* error code on failure.
*/
-
/*
* Frees secondary storage associated with the dwc2_hsotg structure contained
* in the struct usb_hcd field
@@ -2142,40 +2171,21 @@ static void dwc2_hcd_release(struct dwc2
}
/*
- * Sets all parameters to the given value.
- *
- * Assumes that the dwc2_core_params struct contains only integers.
- */
-void dwc2_set_all_params(struct dwc2_core_params *params, int value)
-{
- int *p = (int *)params;
- size_t size = sizeof(*params) / sizeof(*p);
- int i;
-
- for (i = 0; i < size; i++)
- p[i] = value;
-}
-
-/*
* Initializes the HCD. This function allocates memory for and initializes the
* static parts of the usb_hcd and dwc2_hsotg structures. It also registers the
* USB bus with the core and calls the hc_driver->start() function. It returns
* a negative error on failure.
*/
-int dwc2_hcd_init(struct dwc2_hsotg *hsotg,
- const struct dwc2_core_params *params)
+int dwc2_hcd_init(struct dwc2_hsotg *hsotg)
{
struct dwc2_host_chan *channel;
int i, num_channels;
int err, retval;
- dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
-
- /* Detect config values from hardware */
- retval = dwc2_get_hwparams(hsotg);
+ if (usb_disabled())
+ return -ENODEV;
- if (retval)
- return retval;
+ dev_dbg(hsotg->dev, "DWC OTG HCD INIT\n");
retval = -ENOMEM;
@@ -2194,15 +2204,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso
hsotg->last_frame_num = HFNUM_MAX_FRNUM;
#endif
- hsotg->core_params = kmem_zalloc(sizeof(*hsotg->core_params), KM_SLEEP);
- if (!hsotg->core_params)
- goto error1;
-
- dwc2_set_all_params(hsotg->core_params, -1);
-
- /* Validate parameter values */
- dwc2_set_parameters(hsotg, params);
-
spin_lock_init(&hsotg->lock);
/*
@@ -2306,7 +2307,6 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso
error3:
dwc2_hcd_release(hsotg);
error2:
-error1:
kmem_free(hsotg->core_params, sizeof(*hsotg->core_params));
#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
@@ -2319,3 +2319,30 @@ error1:
dev_err(hsotg->dev, "%s() FAILED, returning %d\n", __func__, retval);
return retval;
}
+
+/*
+ * Removes the HCD.
+ * Frees memory and resources associated with the HCD and deregisters the bus.
+ */
+void dwc2_hcd_remove(struct dwc2_hsotg *hsotg)
+{
+ struct usb_hcd *hcd;
+
+ dev_dbg(hsotg->dev, "DWC OTG HCD REMOVE\n");
+
+ hcd = dwc2_hsotg_to_hcd(hsotg);
+ dev_dbg(hsotg->dev, "hsotg->hcd = %p\n", hcd);
+
+ if (!hcd) {
+ dev_dbg(hsotg->dev, "%s: dwc2_hsotg_to_hcd(hsotg) NULL!\n",
+ __func__);
+ return;
+ }
+ hsotg->priv = NULL;
+ dwc2_hcd_release(hsotg);
+
+#ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
+ kfree(hsotg->last_frame_num_array);
+ kfree(hsotg->frame_num_array);
+#endif
+}
Index: src/sys/external/bsd/dwc2/dist/dwc2_hcd.h
diff -u src/sys/external/bsd/dwc2/dist/dwc2_hcd.h:1.9 src/sys/external/bsd/dwc2/dist/dwc2_hcd.h:1.10
--- src/sys/external/bsd/dwc2/dist/dwc2_hcd.h:1.9 Wed Sep 3 10:00:08 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_hcd.h Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcd.h,v 1.9 2014/09/03 10:00:08 skrll Exp $ */
+/* $NetBSD: dwc2_hcd.h,v 1.10 2015/08/30 12:59:59 skrll Exp $ */
/*
* hcd.h - DesignWare HS OTG Controller host-mode declarations
@@ -249,7 +249,8 @@ enum dwc2_transaction_type {
* @ntd: Actual number of transfer descriptors in a list
* @dw_align_buf: Used instead of original buffer if its physical address
* is not dword-aligned
- * @dw_align_buf_dma: DMA address for align_buf
+ * @dw_align_buf_size: Size of dw_align_buf
+ * @dw_align_buf_dma: DMA address for dw_align_buf
* @qtd_list: List of QTDs for this QH
* @channel: Host channel currently processing transfers for this QH
* @qh_list_entry: Entry for QH in either the periodic or non-periodic
@@ -284,6 +285,7 @@ struct dwc2_qh {
u16 ntd;
usb_dma_t dw_align_buf_usbdma;
u8 *dw_align_buf;
+ int dw_align_buf_size;
dma_addr_t dw_align_buf_dma;
struct list_head qtd_list;
struct dwc2_host_chan *channel;
@@ -459,13 +461,8 @@ static inline u8 dwc2_hcd_is_pipe_out(st
return !dwc2_hcd_is_pipe_in(pipe);
}
-extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg,
- const struct dwc2_core_params *params);
+extern int dwc2_hcd_init(struct dwc2_hsotg *hsotg);
extern void dwc2_hcd_remove(struct dwc2_hsotg *hsotg);
-extern void dwc2_set_parameters(struct dwc2_hsotg *hsotg,
- const struct dwc2_core_params *params);
-extern void dwc2_set_all_params(struct dwc2_core_params *params, int value);
-extern int dwc2_get_hwparams(struct dwc2_hsotg *hsotg);
/* Transaction Execution Functions */
extern enum dwc2_transaction_type dwc2_hcd_select_transactions(
@@ -476,6 +473,9 @@ extern void dwc2_hcd_queue_transactions(
/* Schedule Queue Functions */
/* Implemented in hcd_queue.c */
extern void dwc2_hcd_init_usecs(struct dwc2_hsotg *hsotg);
+extern struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
+ struct dwc2_hcd_urb *urb,
+ gfp_t mem_flags);
extern void dwc2_hcd_qh_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
extern void dwc2_hcd_qh_unlink(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh);
@@ -484,7 +484,7 @@ extern void dwc2_hcd_qh_deactivate(struc
extern void dwc2_hcd_qtd_init(struct dwc2_qtd *qtd, struct dwc2_hcd_urb *urb);
extern int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
- struct dwc2_qh **qh, int mem_flags);
+ struct dwc2_qh *qh);
/* Removes and frees a QTD */
extern void dwc2_hcd_qtd_unlink_and_free(struct dwc2_hsotg *hsotg,
@@ -667,9 +667,6 @@ extern irqreturn_t dwc2_handle_hcd_intr(
*/
extern void dwc2_hcd_stop(struct dwc2_hsotg *hsotg);
-extern void dwc2_hcd_start(struct dwc2_hsotg *hsotg);
-extern void dwc2_hcd_disconnect(struct dwc2_hsotg *hsotg);
-
/**
* dwc2_hcd_is_b_host() - Returns 1 if core currently is acting as B host,
* and 0 otherwise
@@ -679,13 +676,6 @@ extern void dwc2_hcd_disconnect(struct d
extern int dwc2_hcd_is_b_host(struct dwc2_hsotg *hsotg);
/**
- * dwc2_hcd_get_frame_number() - Returns current frame number
- *
- * @hsotg: The DWC2 HCD
- */
-extern int dwc2_hcd_get_frame_number(struct dwc2_hsotg *hsotg);
-
-/**
* dwc2_hcd_dump_state() - Dumps hsotg state
*
* @hsotg: The DWC2 HCD
@@ -774,8 +764,9 @@ int dwc2_hcd_urb_dequeue(struct dwc2_hso
void dwc2_hcd_reinit(struct dwc2_hsotg *);
int dwc2_hcd_hub_control(struct dwc2_hsotg *, u16, u16, u16, char *, u16);
struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *);
-int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *, struct dwc2_hcd_urb *, void **,
- gfp_t);
+int dwc2_hcd_urb_enqueue(struct dwc2_hsotg *hsotg,
+ struct dwc2_hcd_urb *urb, struct dwc2_qh *qh,
+ struct dwc2_qtd *qtd);
void dwc2_hcd_urb_set_pipeinfo(struct dwc2_hsotg *, struct dwc2_hcd_urb *,
u8 ,u8, u8, u8, u16);
Index: src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c
diff -u src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c:1.11 src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c:1.12
--- src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c:1.11 Mon Nov 24 10:14:14 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_hcdintr.c Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcdintr.c,v 1.11 2014/11/24 10:14:14 skrll Exp $ */
+/* $NetBSD: dwc2_hcdintr.c,v 1.12 2015/08/30 12:59:59 skrll Exp $ */
/*
* hcd_intr.c - DesignWare HS OTG Controller host-mode interrupt handling
@@ -40,7 +40,7 @@
* This file contains the interrupt handlers for Host mode
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdintr.c,v 1.11 2014/11/24 10:14:14 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdintr.c,v 1.12 2015/08/30 12:59:59 skrll Exp $");
#include <sys/types.h>
#include <sys/pool.h>
@@ -357,6 +357,9 @@ static void dwc2_port_intr(struct dwc2_h
dev_vdbg(hsotg->dev,
"--Port Interrupt HPRT0=0x%08x Port Connect Detected--\n",
hprt0);
+ if (hsotg->lx_state != DWC2_L0)
+ usb_hcd_resume_root_hub(hsotg->priv);
+
hsotg->flags.b.port_connect_status_change = 1;
hsotg->flags.b.port_connect_status = 1;
hprt0_modify |= HPRT0_CONNDET;
@@ -474,12 +477,17 @@ static int dwc2_update_urb_state(struct
}
/* Non DWORD-aligned buffer case handling */
- if (chan->align_buf && xfer_length && chan->ep_is_in) {
+ if (chan->align_buf && xfer_length) {
dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
- usb_syncmem(urb->usbdma, 0, urb->length, BUS_DMASYNC_POSTREAD);
- memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
- xfer_length);
- usb_syncmem(urb->usbdma, 0, urb->length, BUS_DMASYNC_PREREAD);
+ usb_syncmem(urb->usbdma, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ if (chan->ep_is_in)
+ memcpy(urb->buf + urb->actual_length,
+ chan->qh->dw_align_buf, xfer_length);
+ usb_syncmem(urb->usbdma, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
dev_vdbg(hsotg->dev, "urb->actual_length=%d xfer_length=%d\n",
@@ -564,17 +572,22 @@ static enum dwc2_halt_status dwc2_update
chan, chnum, qtd, halt_status, NULL);
/* Non DWORD-aligned buffer case handling */
- if (chan->align_buf && frame_desc->actual_length &&
- chan->ep_is_in) {
+ if (chan->align_buf && frame_desc->actual_length) {
dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
__func__);
- usb_syncmem(urb->usbdma, 0, urb->length,
- BUS_DMASYNC_POSTREAD);
- memcpy(urb->buf + frame_desc->offset +
- qtd->isoc_split_offset, chan->qh->dw_align_buf,
- frame_desc->actual_length);
- usb_syncmem(urb->usbdma, 0, urb->length,
- BUS_DMASYNC_PREREAD);
+ usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma;
+
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ if (chan->ep_is_in)
+ memcpy(urb->buf + frame_desc->offset +
+ qtd->isoc_split_offset,
+ chan->qh->dw_align_buf,
+ frame_desc->actual_length);
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
break;
case DWC2_HC_XFER_FRAME_OVERRUN:
@@ -597,17 +610,22 @@ static enum dwc2_halt_status dwc2_update
chan, chnum, qtd, halt_status, NULL);
/* Non DWORD-aligned buffer case handling */
- if (chan->align_buf && frame_desc->actual_length &&
- chan->ep_is_in) {
+ if (chan->align_buf && frame_desc->actual_length) {
dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n",
__func__);
- usb_syncmem(urb->usbdma, 0, urb->length,
- BUS_DMASYNC_POSTREAD);
- memcpy(urb->buf + frame_desc->offset +
- qtd->isoc_split_offset, chan->qh->dw_align_buf,
- frame_desc->actual_length);
- usb_syncmem(urb->usbdma, 0, urb->length,
- BUS_DMASYNC_PREREAD);
+ usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma;
+
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ if (chan->ep_is_in)
+ memcpy(urb->buf + frame_desc->offset +
+ qtd->isoc_split_offset,
+ chan->qh->dw_align_buf,
+ frame_desc->actual_length);
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
/* Skip whole frame */
@@ -943,12 +961,12 @@ static int dwc2_xfercomp_isoc_split_in(s
if (chan->align_buf) {
dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
- usb_syncmem(qtd->urb->usbdma, 0, qtd->urb->length,
- BUS_DMASYNC_POSTREAD);
+ usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma,
+ chan->qh->dw_align_buf_size, BUS_DMASYNC_POSTREAD);
memcpy(qtd->urb->buf + frame_desc->offset +
qtd->isoc_split_offset, chan->qh->dw_align_buf, len);
- usb_syncmem(qtd->urb->usbdma, 0, qtd->urb->length,
- BUS_DMASYNC_PREREAD);
+ usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma,
+ chan->qh->dw_align_buf_size, BUS_DMASYNC_PREREAD);
}
qtd->isoc_split_offset += len;
@@ -1175,10 +1193,19 @@ static void dwc2_update_urb_state_abn(st
/* Non DWORD-aligned buffer case handling */
if (chan->align_buf && xfer_length && chan->ep_is_in) {
dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__);
- usb_syncmem(urb->usbdma, 0, urb->length, BUS_DMASYNC_POSTREAD);
- memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf,
- xfer_length);
- usb_syncmem(urb->usbdma, 0, urb->length, BUS_DMASYNC_PREREAD);
+
+ usb_dma_t *ud = &chan->qh->dw_align_buf_usbdma;
+
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
+ if (chan->ep_is_in)
+ memcpy(urb->buf + urb->actual_length,
+ chan->qh->dw_align_buf,
+ xfer_length);
+ usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,
+ chan->ep_is_in ?
+ BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
}
urb->actual_length += xfer_length;
@@ -1206,6 +1233,16 @@ static void dwc2_hc_nak_intr(struct dwc2
struct dwc2_host_chan *chan, int chnum,
struct dwc2_qtd *qtd)
{
+ if (!qtd) {
+ dev_dbg(hsotg->dev, "%s: qtd is NULL\n", __func__);
+ return;
+ }
+
+ if (!qtd->urb) {
+ dev_dbg(hsotg->dev, "%s: qtd->urb is NULL\n", __func__);
+ return;
+ }
+
if (dbg_hc(chan))
dev_vdbg(hsotg->dev, "--Host Channel %d Interrupt: NAK Received--\n",
chnum);
@@ -1910,10 +1947,10 @@ static void dwc2_hc_chhltd_intr_dma(stru
"NYET/NAK/ACK/other in non-error case, 0x%08x\n",
chan->hcint);
error:
- /* use the 3-strikes rule */
+ /* Failthrough: use 3-strikes rule */
qtd->error_count++;
dwc2_update_urb_state_abn(hsotg, chan, chnum, qtd->urb,
- qtd, DWC2_HC_XFER_XACT_ERR);
+ qtd, DWC2_HC_XFER_XACT_ERR);
dwc2_hcd_save_data_toggle(hsotg, chan, chnum, qtd);
dwc2_halt_channel(hsotg, chan, qtd, DWC2_HC_XFER_XACT_ERR);
}
Index: src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c
diff -u src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c:1.11 src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c:1.12
--- src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c:1.11 Wed Sep 3 10:00:08 2014
+++ src/sys/external/bsd/dwc2/dist/dwc2_hcdqueue.c Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hcdqueue.c,v 1.11 2014/09/03 10:00:08 skrll Exp $ */
+/* $NetBSD: dwc2_hcdqueue.c,v 1.12 2015/08/30 12:59:59 skrll Exp $ */
/*
* hcd_queue.c - DesignWare HS OTG Controller host queuing routines
@@ -42,7 +42,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.11 2014/09/03 10:00:08 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dwc2_hcdqueue.c,v 1.12 2015/08/30 12:59:59 skrll Exp $");
#include <sys/types.h>
#include <sys/kmem.h>
@@ -206,7 +206,7 @@ static void dwc2_qh_init(struct dwc2_hso
*
* Return: Pointer to the newly allocated QH, or NULL on error
*/
-static struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
+struct dwc2_qh *dwc2_hcd_qh_create(struct dwc2_hsotg *hsotg,
struct dwc2_hcd_urb *urb,
gfp_t mem_flags)
{
@@ -251,8 +251,8 @@ void dwc2_hcd_qh_free(struct dwc2_hsotg
if (hsotg->core_params->dma_desc_enable > 0) {
dwc2_hcd_qh_free_ddma(hsotg, qh);
} else if (qh->dw_align_buf) {
- /* XXXNH */
- usb_freemem(&hsotg->hsotg_sc->sc_bus, &qh->dw_align_buf_usbdma);
+ usb_freemem(&sc->sc_bus, &qh->dw_align_buf_usbdma);
+ qh->dw_align_buf_dma = (dma_addr_t)0;
}
pool_cache_put(sc->sc_qhpool, qh);
@@ -609,6 +609,7 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *h
&hsotg->non_periodic_sched_inactive);
return 0;
}
+
status = dwc2_schedule_periodic(hsotg, qh);
if (status)
return status;
@@ -646,6 +647,7 @@ void dwc2_hcd_qh_unlink(struct dwc2_hsot
list_del_init(&qh->qh_list_entry);
return;
}
+
dwc2_deschedule_periodic(hsotg, qh);
hsotg->periodic_qh_count--;
if (!hsotg->periodic_qh_count) {
@@ -780,63 +782,39 @@ void dwc2_hcd_qtd_init(struct dwc2_qtd *
/**
* dwc2_hcd_qtd_add() - Adds a QTD to the QTD-list of a QH
+ * Caller must hold driver lock.
*
- * @hsotg: The DWC HCD structure
- * @qtd: The QTD to add
- * @qh: Out parameter to return queue head
- * @mem_flags: Flag to do atomic alloc if needed
+ * @hsotg: The DWC HCD structure
+ * @qtd: The QTD to add
+ * @qh: Queue head to add qtd to
*
* Return: 0 if successful, negative error code otherwise
*
- * Finds the correct QH to place the QTD into. If it does not find a QH, it
- * will create a new QH. If the QH to which the QTD is added is not currently
- * scheduled, it is placed into the proper schedule based on its EP type.
- *
- * HCD lock must be held and interrupts must be disabled on entry
+ * If the QH to which the QTD is added is not currently scheduled, it is placed
+ * into the proper schedule based on its EP type.
*/
int dwc2_hcd_qtd_add(struct dwc2_hsotg *hsotg, struct dwc2_qtd *qtd,
- struct dwc2_qh **qh, gfp_t mem_flags)
+ struct dwc2_qh *qh)
{
- struct dwc2_hcd_urb *urb = qtd->urb;
- int allocated = 0;
+
+ KASSERT(mutex_owned(hsotg->lock));
int retval;
- /*
- * Get the QH which holds the QTD-list to insert to. Create QH if it
- * doesn't exist.
- */
- if (*qh == NULL) {
- *qh = dwc2_hcd_qh_create(hsotg, urb, mem_flags);
- if (*qh == NULL)
- return -ENOMEM;
- allocated = 1;
+ if (unlikely(!qh)) {
+ dev_err(hsotg->dev, "%s: Invalid QH\n", __func__);
+ retval = -EINVAL;
+ goto fail;
}
- retval = dwc2_hcd_qh_add(hsotg, *qh);
+ retval = dwc2_hcd_qh_add(hsotg, qh);
if (retval)
goto fail;
- qtd->qh = *qh;
- list_add_tail(&qtd->qtd_list_entry, &(*qh)->qtd_list);
+ qtd->qh = qh;
+ list_add_tail(&qtd->qtd_list_entry, &qh->qtd_list);
return 0;
-
fail:
- if (allocated) {
- struct dwc2_qtd *qtd2, *qtd2_tmp;
- struct dwc2_qh *qh_tmp = *qh;
-
- *qh = NULL;
- dwc2_hcd_qh_unlink(hsotg, qh_tmp);
-
- /* Free each QTD in the QH's QTD list */
- list_for_each_entry_safe(qtd2, qtd2_tmp, &qh_tmp->qtd_list,
- qtd_list_entry)
- dwc2_hcd_qtd_unlink_and_free(hsotg, qtd2, qh_tmp);
-
- dwc2_hcd_qh_free(hsotg, qh_tmp);
- }
-
return retval;
}
Index: src/sys/external/bsd/dwc2/dist/dwc2_hw.h
diff -u src/sys/external/bsd/dwc2/dist/dwc2_hw.h:1.2 src/sys/external/bsd/dwc2/dist/dwc2_hw.h:1.3
--- src/sys/external/bsd/dwc2/dist/dwc2_hw.h:1.2 Wed Sep 25 06:19:22 2013
+++ src/sys/external/bsd/dwc2/dist/dwc2_hw.h Sun Aug 30 12:59:59 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: dwc2_hw.h,v 1.2 2013/09/25 06:19:22 skrll Exp $ */
+/* $NetBSD: dwc2_hw.h,v 1.3 2015/08/30 12:59:59 skrll Exp $ */
/*
* hw.h - DesignWare HS OTG Controller hardware definitions
@@ -111,6 +111,7 @@
#define GUSBCFG_FSINTF (1 << 5)
#define GUSBCFG_ULPI_UTMI_SEL (1 << 4)
#define GUSBCFG_PHYIF16 (1 << 3)
+#define GUSBCFG_PHYIF8 (0 << 3)
#define GUSBCFG_TOUTCAL_MASK (0x7 << 0)
#define GUSBCFG_TOUTCAL_SHIFT 0
#define GUSBCFG_TOUTCAL_LIMIT 0x7
@@ -295,6 +296,7 @@
#define GHWCFG4_NUM_IN_EPS_MASK (0xf << 26)
#define GHWCFG4_NUM_IN_EPS_SHIFT 26
#define GHWCFG4_DED_FIFO_EN (1 << 25)
+#define GHWCFG4_DED_FIFO_SHIFT 25
#define GHWCFG4_SESSION_END_FILT_EN (1 << 24)
#define GHWCFG4_B_VALID_FILT_EN (1 << 23)
#define GHWCFG4_A_VALID_FILT_EN (1 << 22)
@@ -405,6 +407,7 @@
#define FIFOSIZE_DEPTH_SHIFT 16
#define FIFOSIZE_STARTADDR_MASK (0xffff << 0)
#define FIFOSIZE_STARTADDR_SHIFT 0
+#define FIFOSIZE_DEPTH_GET(_x) (((_x) >> 16) & 0xffff)
/* Device mode registers */
@@ -521,11 +524,11 @@
#define DXEPCTL_STALL (1 << 21)
#define DXEPCTL_SNP (1 << 20)
#define DXEPCTL_EPTYPE_MASK (0x3 << 18)
-#define DXEPCTL_EPTYPE_SHIFT 18
-#define DXEPCTL_EPTYPE_CONTROL 0
-#define DXEPCTL_EPTYPE_ISO 1
-#define DXEPCTL_EPTYPE_BULK 2
-#define DXEPCTL_EPTYPE_INTTERUPT 3
+#define DXEPCTL_EPTYPE_CONTROL (0x0 << 18)
+#define DXEPCTL_EPTYPE_ISO (0x1 << 18)
+#define DXEPCTL_EPTYPE_BULK (0x2 << 18)
+#define DXEPCTL_EPTYPE_INTERRUPT (0x3 << 18)
+
#define DXEPCTL_NAKSTS (1 << 17)
#define DXEPCTL_DPID (1 << 16)
#define DXEPCTL_EOFRNUM (1 << 16)
@@ -541,6 +544,7 @@
#define DIEPINT(_a) HSOTG_REG(0x908 + ((_a) * 0x20))
#define DOEPINT(_a) HSOTG_REG(0xB08 + ((_a) * 0x20))
+#define DXEPINT_SETUP_RCVD (1 << 15)
#define DXEPINT_INEPNAKEFF (1 << 6)
#define DXEPINT_BACK2BACKSETUP (1 << 6)
#define DXEPINT_INTKNEPMIS (1 << 5)