[U-Boot] [RFC PATCH] usb: add driver for Synopsis DWC2 USB IP block
Stephen Warren
swarren at wwwdotorg.org
Thu Feb 6 06:27:01 CET 2014
From: Oleksandr Tymoshenko <gonzo at bluezbox.com>
This is the USB host controller used on the Raspbery Pi.
swarren changelog:
* Fixed prototype of usb_lowlevel_init() to match upstream change.
* Fixed a number of unused variable warnings.
* Replaced license headers with SPDX tags.
* Renamed files DWC -> DWC2 to make it clear which HW it's for.
* Many hundreds of checkpatch fixes.
Signed-off-by: Oleksandr Tymoshenko <gonzo at bluezbox.com>
Signed-off-by: Stephen Warren <swarren at wwdotorg.org>
---
I've fixed all the checkpatch errors. There are hundreds of warnings left.
Still, I figured it was a good idea to post the patch for review of any
other aspects.
---
drivers/usb/host/Makefile | 2 +
drivers/usb/host/dwc2_otg-hcd.c | 730 ++++++++++++
drivers/usb/host/dwc2_otg.c | 2179 +++++++++++++++++++++++++++++++++++
drivers/usb/host/dwc2_otg.h | 130 +++
drivers/usb/host/dwc2_otg_core_if.h | 1001 ++++++++++++++++
drivers/usb/host/dwc2_otg_regs.h | 1625 ++++++++++++++++++++++++++
include/usb.h | 3 +-
7 files changed, 5669 insertions(+), 1 deletion(-)
create mode 100644 drivers/usb/host/dwc2_otg-hcd.c
create mode 100644 drivers/usb/host/dwc2_otg.c
create mode 100644 drivers/usb/host/dwc2_otg.h
create mode 100644 drivers/usb/host/dwc2_otg_core_if.h
create mode 100644 drivers/usb/host/dwc2_otg_regs.h
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 1417028..75bd615 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -42,3 +42,5 @@ obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o
obj-$(CONFIG_USB_XHCI) += xhci.o xhci-mem.o xhci-ring.o
obj-$(CONFIG_USB_XHCI_EXYNOS) += xhci-exynos5.o
obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o
+
+obj-$(CONFIG_USB_DWC2_OTG) += dwc2_otg.o dwc2_otg-hcd.o
diff --git a/drivers/usb/host/dwc2_otg-hcd.c b/drivers/usb/host/dwc2_otg-hcd.c
new file mode 100644
index 0000000..c7d45c7
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg-hcd.c
@@ -0,0 +1,730 @@
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <malloc.h>
+#include "dwc2_otg.h"
+#include "dwc2_otg_regs.h"
+#include "dwc2_otg_core_if.h"
+
+#define STATUS_ACK_HLT_COMPL 0x23
+#define CHANNEL 0
+
+#define DWC_OTG_HCD_STATUS_BUF_SIZE 64
+#define DWC_OTG_HCD_DATA_BUF_SIZE (64 * 1024)
+
+static int root_hub_devnum;
+
+static uint8_t *allocated_buffer;
+static uint8_t *aligned_buffer;
+static uint8_t *status_buffer;
+
+static dwc_otg_core_if_t g_core_if;
+
+#define MAX_DEVICE 16
+#define MAX_ENDPOINT 8
+int bulk_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+int control_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
+
+void do_hang(int line, uint32_t d)
+{
+ printf("DWC OTG: hang at line %d: %08x\n", line, d);
+ while (1)
+ udelay(10);
+}
+
+void handle_error(int line, uint32_t d)
+{
+ hcint_data_t hcint;
+ hcint.d32 = d;
+
+ printf("Error condition at line %d: ", line);
+ if (hcint.b.ahberr)
+ printf(" AHBERR");
+ if (hcint.b.stall)
+ printf(" STALL");
+ if (hcint.b.bblerr)
+ printf(" NAK");
+ if (hcint.b.ack)
+ printf(" ACK");
+ if (hcint.b.nyet)
+ printf(" NYET");
+ if (hcint.b.xacterr)
+ printf(" XACTERR");
+ if (hcint.b.datatglerr)
+ printf(" DATATGLERR");
+ printf("\n");
+}
+
+/*
+ * U-Boot USB interface
+ */
+int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+{
+ /*
+ * We need doubleword-aligned buffers for DMA transfers
+ */
+ allocated_buffer = (uint8_t *)malloc(DWC_OTG_HCD_STATUS_BUF_SIZE + DWC_OTG_HCD_DATA_BUF_SIZE + 8);
+ uint32_t addr = (uint32_t)allocated_buffer;
+ aligned_buffer = (uint8_t *) ((addr + 7) & ~7);
+ status_buffer = (uint8_t *)((uint32_t)aligned_buffer + DWC_OTG_HCD_DATA_BUF_SIZE);
+ int i, j;
+ hprt0_data_t hprt0 = {.d32 = 0 };
+
+ root_hub_devnum = 0;
+ memset(&g_core_if, 0, sizeof(g_core_if));
+ dwc_otg_cil_init(&g_core_if, (uint32_t *)0x20980000);
+
+ if ((g_core_if.snpsid & 0xFFFFF000) !=
+ 0x4F542000) {
+ printf("SNPSID is invalid (not DWC OTG device): %08x\n", g_core_if.snpsid);
+ return -1;
+ }
+
+ dwc_otg_core_init(&g_core_if);
+ dwc_otg_core_host_init(&g_core_if);
+
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtrst = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ udelay(50000);
+ hprt0.b.prtrst = 0;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+
+ udelay(50000);
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+
+ for (i = 0; i < MAX_DEVICE; i++) {
+ for (j = 0; j < MAX_ENDPOINT; j++) {
+ control_data_toggle[i][j] = DWC_OTG_HC_PID_DATA1;
+ bulk_data_toggle[i][j] = DWC_OTG_HC_PID_DATA0;
+ }
+ }
+
+ return 0;
+}
+
+int usb_lowlevel_stop(int index)
+{
+ free(allocated_buffer);
+
+ return 0;
+}
+
+/* based on usb_ohci.c */
+#define min_t(type, x, y) \
+ ({ type __x = (x); type __y = (y); __x < __y ? __x : __y; })
+/*-------------------------------------------------------------------------*
+ * Virtual Root Hub
+ *-------------------------------------------------------------------------*/
+
+/* Device descriptor */
+static __u8 root_hub_dev_des[] = {
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x10, /* __u16 bcdUSB; v1.1 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x01, /* __u8 iManufacturer; */
+ 0x02, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] = {
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes; */
+
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x08, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static unsigned char root_hub_str_index0[] = {
+ 0x04, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 0x09, /* __u8 lang ID */
+ 0x04, /* __u8 lang ID */
+};
+
+static unsigned char root_hub_str_index1[] = {
+ 32, /* __u8 bLength; */
+ 0x03, /* __u8 bDescriptorType; String-descriptor */
+ 'D', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'W', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'C', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'O', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'T', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'G', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ ' ', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'R', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'o', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 't', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'H', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'u', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+ 'b', /* __u8 Unicode */
+ 0, /* __u8 Unicode */
+};
+
+static int dwc_otg_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
+ void *buffer, int transfer_len,
+ struct devrequest *cmd)
+{
+ int leni = transfer_len;
+ int len = 0;
+ int stat = 0;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wLength;
+ unsigned char data[32];
+ hprt0_data_t hprt0 = {.d32 = 0 };
+
+ if (usb_pipeint(pipe)) {
+ printf("Root-Hub submit IRQ: NOT implemented");
+ return 0;
+ }
+
+ bmRType_bReq = cmd->requesttype | (cmd->request << 8);
+ wValue = cpu_to_le16 (cmd->value);
+ wLength = cpu_to_le16 (cmd->length);
+
+ switch (bmRType_bReq) {
+ case RH_GET_STATUS:
+ *(__u16 *)buffer = cpu_to_le16(1);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *)buffer = cpu_to_le16(0);
+ len = 2;
+ break;
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *)buffer = cpu_to_le32(0);
+ len = 4;
+ break;
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ {
+ uint32_t port_status = 0;
+ uint32_t port_change = 0;
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+ if (hprt0.b.prtconnsts)
+ port_status |= USB_PORT_STAT_CONNECTION;
+ if (hprt0.b.prtena)
+ port_status |= USB_PORT_STAT_ENABLE;
+ if (hprt0.b.prtsusp)
+ port_status |= USB_PORT_STAT_SUSPEND;
+ if (hprt0.b.prtovrcurract)
+ port_status |= USB_PORT_STAT_OVERCURRENT;
+ if (hprt0.b.prtrst)
+ port_status |= USB_PORT_STAT_RESET;
+ if (hprt0.b.prtpwr)
+ port_status |= USB_PORT_STAT_POWER;
+
+ port_status |= USB_PORT_STAT_HIGH_SPEED;
+
+ if (hprt0.b.prtenchng)
+ port_change |= USB_PORT_STAT_C_ENABLE;
+ if (hprt0.b.prtconndet)
+ port_change |= USB_PORT_STAT_C_CONNECTION;
+ if (hprt0.b.prtovrcurrchng)
+ port_change |= USB_PORT_STAT_C_OVERCURRENT;
+
+ *(__u32 *)buffer = cpu_to_le32(port_status |
+ (port_change << 16));
+ len = 4;
+ }
+ break;
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ break;
+
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case RH_C_PORT_CONNECTION:
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+ hprt0.b.prtconndet = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ break;
+ }
+ break;
+
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case (RH_PORT_SUSPEND):
+ break;
+
+ case (RH_PORT_RESET):
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtrst = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ udelay(500);
+ hprt0.b.prtrst = 0;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+
+ udelay(500);
+ hprt0.d32 = dwc_read_reg32(g_core_if.host_if->hprt0);
+
+ break;
+
+ case (RH_PORT_POWER):
+ hprt0.d32 = dwc_otg_read_hprt0(&g_core_if);
+ hprt0.b.prtpwr = 1;
+ dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32);
+ break;
+
+ case (RH_PORT_ENABLE):
+ break;
+ }
+ break;
+ case RH_SET_ADDRESS:
+ root_hub_devnum = wValue;
+ break;
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case (0x01): /* device descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_dev_des),
+ wLength));
+ memcpy(buffer, root_hub_dev_des, len);
+ break;
+ case (0x02): /* configuration descriptor */
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_config_des),
+ wLength));
+ memcpy(buffer, root_hub_config_des, len);
+ break;
+ case (0x03): /* string descriptors */
+ if (wValue == 0x0300) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index0),
+ wLength));
+ memcpy(buffer, root_hub_str_index0, len);
+ }
+ if (wValue == 0x0301) {
+ len = min_t(unsigned int,
+ leni,
+ min_t(unsigned int,
+ sizeof(root_hub_str_index1),
+ wLength));
+ memcpy(buffer, root_hub_str_index1, len);
+ }
+ break;
+ default:
+ stat = USB_ST_STALLED;
+ }
+ break;
+
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ {
+ __u32 temp = 0x00000001;
+
+ data[0] = 9; /* min length; */
+ data[1] = 0x29;
+ data[2] = temp & RH_A_NDP;
+ data[3] = 0;
+ if (temp & RH_A_PSM)
+ data[3] |= 0x1;
+ if (temp & RH_A_NOCP)
+ data[3] |= 0x10;
+ else if (temp & RH_A_OCPM)
+ data[3] |= 0x8;
+
+ /* corresponds to data[4-7] */
+ data[5] = (temp & RH_A_POTPGT) >> 24;
+ data[7] = temp & RH_B_DR;
+ if (data[2] < 7) {
+ data[8] = 0xff;
+ } else {
+ data[0] += 2;
+ data[8] = (temp & RH_B_DR) >> 8;
+ data[10] = data[9] = 0xff;
+ }
+
+ len = min_t(unsigned int, leni,
+ min_t(unsigned int, data[0], wLength));
+ memcpy(buffer, data, len);
+ break;
+ }
+
+ case RH_GET_CONFIGURATION:
+ *(__u8 *) buffer = 0x01;
+ len = 1;
+ break;
+ case RH_SET_CONFIGURATION:
+ break;
+ default:
+ printf("unsupported root hub command\n");
+ stat = USB_ST_STALLED;
+ }
+
+ mdelay(1);
+
+ len = min_t(int, len, leni);
+
+ dev->act_len = len;
+ dev->status = stat;
+
+ return stat;
+
+}
+
+int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len)
+{
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ int done = 0;
+ hctsiz_data_t hctsiz;
+ dwc_otg_host_if_t *host_if = g_core_if.host_if;
+ dwc_otg_hc_regs_t *hc_regs;
+ hcint_data_t hcint;
+ hcint_data_t hcint_new;
+ uint32_t max_hc_xfer_size = g_core_if.core_params->max_transfer_size;
+ uint16_t max_hc_pkt_count = g_core_if.core_params->max_packet_count;
+ uint32_t xfer_len;
+ uint32_t num_packets;
+ int stop_transfer = 0;
+
+ if (len > DWC_OTG_HCD_DATA_BUF_SIZE) {
+ printf("submit_bulk_msg: %d is more then available buffer size(%d)\n", len, DWC_OTG_HCD_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = done;
+ return -1;
+ }
+
+ hc_regs = host_if->hc_regs[CHANNEL];
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ return -1;
+ }
+
+ while ((done < len) && !stop_transfer) {
+ /* Initialize channel */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, usb_pipein(pipe), DWC_OTG_EP_TYPE_BULK, max);
+
+ xfer_len = (len - done);
+ if (xfer_len > max_hc_xfer_size)
+ /* Make sure that xfer_len is a multiple of max packet size. */
+ xfer_len = max_hc_xfer_size - max + 1;
+
+ if (xfer_len > 0) {
+ num_packets = (xfer_len + max - 1) / max;
+ if (num_packets > max_hc_pkt_count) {
+ num_packets = max_hc_pkt_count;
+ xfer_len = num_packets * max;
+ }
+ } else
+ num_packets = 1;
+
+ if (usb_pipein(pipe))
+ xfer_len = num_packets * max;
+
+ hctsiz.d32 = 0;
+
+ hctsiz.b.xfersize = xfer_len;
+ hctsiz.b.pktcnt = num_packets;
+ hctsiz.b.pid = bulk_data_toggle[devnum][ep];
+
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ memcpy(aligned_buffer, (char *)buffer + done, len - done);
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)aligned_buffer);
+
+ hcchar_data_t hcchar;
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Remember original int status */
+ hcint.d32 = dwc_read_reg32(&hc_regs->hcint);
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ /* TODO: no endless loop */
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint.d32 != hcint_new.d32) {
+ hcint.d32 = hcint_new.d32;
+ }
+
+ if (hcint_new.b.ack) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+
+ if (hctsiz.b.pid == DWC_OTG_HC_PID_DATA1)
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ else
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+ }
+
+ if (hcint_new.b.chhltd) {
+ if (hcint_new.b.xfercomp) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+ if (usb_pipein(pipe)) {
+ done += xfer_len - hctsiz.b.xfersize;
+ if (hctsiz.b.xfersize)
+ stop_transfer = 1;
+ } else {
+ done += xfer_len;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL) {
+ handle_error(__LINE__, hcint_new.d32);
+ goto out;
+ }
+
+ break;
+ } else if (hcint_new.b.stall) {
+ printf("DWC OTG: Channel halted\n");
+ bulk_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+
+ stop_transfer = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (done && usb_pipein(pipe))
+ memcpy(buffer, aligned_buffer, done);
+
+ dwc_write_reg32(&hc_regs->hcintmsk, 0);
+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
+out:
+ dev->status = 0;
+ dev->act_len = done;
+
+ return 0;
+}
+
+int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, struct devrequest *setup)
+{
+ int done = 0;
+ int devnum = usb_pipedevice(pipe);
+ int ep = usb_pipeendpoint(pipe);
+ int max = usb_maxpacket(dev, pipe);
+ hctsiz_data_t hctsiz;
+ dwc_otg_host_if_t *host_if = g_core_if.host_if;
+ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[CHANNEL];
+ hcint_data_t hcint_new;
+ /* For CONTROL endpoint pid should start with DATA1 */
+ int status_direction;
+
+ if (devnum == root_hub_devnum) {
+ dev->status = 0;
+ dev->speed = USB_SPEED_HIGH;
+ return dwc_otg_submit_rh_msg(dev, pipe, buffer, len, setup);
+ }
+
+ if (len > DWC_OTG_HCD_DATA_BUF_SIZE) {
+ printf("submit_control_msg: %d is more then available buffer size(%d)\n", len, DWC_OTG_HCD_DATA_BUF_SIZE);
+ dev->status = 0;
+ dev->act_len = done;
+ return -1;
+ }
+
+ /* Initialize channel, OUT for setup buffer */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, 0, DWC_OTG_EP_TYPE_CONTROL, max);
+
+ /* SETUP stage */
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = 8;
+ hctsiz.b.pktcnt = 1;
+ hctsiz.b.pid = DWC_OTG_HC_PID_SETUP;
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)setup);
+
+ hcchar_data_t hcchar;
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ /* TODO: no endless loop */
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd) {
+ break;
+ }
+ }
+
+ /* TODO: check for error */
+ if (!(hcint_new.b.chhltd && hcint_new.b.xfercomp)) {
+ handle_error(__LINE__, hcint_new.d32);
+ goto out;
+ }
+
+ /* Clear interrupts */
+ dwc_write_reg32(&hc_regs->hcintmsk, 0);
+ dwc_write_reg32(&hc_regs->hcint, 0xFFFFFFFF);
+
+ if (buffer) {
+ /* DATA stage */
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, usb_pipein(pipe), DWC_OTG_EP_TYPE_CONTROL, max);
+
+ /* TODO: check if len < 64 */
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = len;
+ hctsiz.b.pktcnt = 1;
+
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ hctsiz.b.pid = control_data_toggle[devnum][ep];
+
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)buffer);
+
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd) {
+ if (hcint_new.b.xfercomp) {
+ hctsiz.d32 = dwc_read_reg32(&hc_regs->hctsiz);
+ if (usb_pipein(pipe))
+ done = len - hctsiz.b.xfersize;
+ else
+ done = len;
+ }
+
+ if (hcint_new.b.ack) {
+ if (hctsiz.b.pid == DWC_OTG_HC_PID_DATA0)
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA0;
+ else
+ control_data_toggle[devnum][ep] = DWC_OTG_HC_PID_DATA1;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL) {
+ goto out;
+ handle_error(__LINE__, hcint_new.d32);
+ }
+
+ break;
+ }
+ }
+ } /* End of DATA stage */
+
+ /* STATUS stage */
+ if ((len == 0) || usb_pipeout(pipe))
+ status_direction = 1;
+ else
+ status_direction = 0;
+
+ dwc_otg_hc_init(&g_core_if, CHANNEL, devnum, ep, status_direction, DWC_OTG_EP_TYPE_CONTROL, max);
+
+ hctsiz.d32 = 0;
+ hctsiz.b.xfersize = 0;
+ hctsiz.b.pktcnt = 1;
+ hctsiz.b.pid = DWC_OTG_HC_PID_DATA1;
+ dwc_write_reg32(&hc_regs->hctsiz, hctsiz.d32);
+
+ dwc_write_reg32(&hc_regs->hcdma, (uint32_t)status_buffer);
+
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.multicnt = 1;
+
+ /* Set host channel enable after all other setup is complete. */
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+
+ while (1) {
+ hcint_new.d32 = dwc_read_reg32(&hc_regs->hcint);
+ if (hcint_new.b.chhltd)
+ break;
+ }
+
+ if (hcint_new.d32 != STATUS_ACK_HLT_COMPL)
+ handle_error(__LINE__, hcint_new.d32);
+
+out:
+ dev->act_len = done;
+ dev->status = 0;
+
+ return done;
+}
+
+int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
+ int len, int interval)
+{
+ printf("dev = %p pipe = %#lx buf = %p size = %d int = %d\n", dev, pipe,
+ buffer, len, interval);
+ return -1;
+}
diff --git a/drivers/usb/host/dwc2_otg.c b/drivers/usb/host/dwc2_otg.c
new file mode 100644
index 0000000..f80a505
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg.c
@@ -0,0 +1,2179 @@
+#include <common.h>
+#include <usb.h>
+#include <malloc.h>
+#include "dwc2_otg.h"
+#include "dwc2_otg_regs.h"
+#include "dwc2_otg_core_if.h"
+
+#undef DWC_OTG_DEBUG
+
+#ifdef DWC_OTG_DEBUG
+ #define PDEBUG(fmt, args...) \
+ printf("[%s:%d] " fmt, \
+ __PRETTY_FUNCTION__, __LINE__ , ## args)
+#else
+ #define PDEBUG(fmt, args...) do {} while (0)
+#endif
+
+void dwc_write_reg32(volatile uint32_t *addr, uint32_t value)
+{
+ *addr = value;
+}
+
+uint32_t dwc_read_reg32(volatile uint32_t *addr)
+{
+ return *addr;
+}
+
+void dwc_modify_reg32(volatile uint32_t *addr, uint32_t clear_mask, uint32_t set_mask)
+{
+ uint32_t v = *addr;
+ *addr = (v & ~clear_mask) | set_mask;
+}
+
+/**
+ * This function returns the mode of the operation, host or device.
+ *
+ * @return 0 - Device Mode, 1 - Host Mode
+ */
+static inline uint32_t dwc_otg_mode(dwc_otg_core_if_t *_core_if)
+{
+ return dwc_read_reg32(&_core_if->core_global_regs->gintsts) & 0x1;
+}
+
+uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t *_core_if)
+{
+ return dwc_otg_mode(_core_if) == DWC_HOST_MODE;
+}
+
+static void dwc_otg_set_uninitialized(int32_t *p, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ p[i] = -1;
+ }
+}
+
+static int dwc_otg_param_initialized(int32_t val)
+{
+ return val != -1;
+}
+
+/**
+ * This function returns the Host All Channel Interrupt register
+ */
+static inline uint32_t dwc_otg_read_host_all_channels_intr(
+ dwc_otg_core_if_t *_core_if)
+{
+ return dwc_read_reg32(&_core_if->host_if->host_global_regs->haint);
+}
+
+static inline uint32_t dwc_otg_read_host_channel_intr(
+ dwc_otg_core_if_t *_core_if, int hc_num)
+{
+ return dwc_read_reg32(&_core_if->host_if->hc_regs[hc_num]->hcint);
+}
+
+/**
+ * This function Reads HPRT0 in preparation to modify. It keeps the
+ * WC bits 0 so that if they are read as 1, they won't clear when you
+ * write it back
+ */
+uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t *_core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(_core_if->host_if->hprt0);
+ hprt0.b.prtena = 0;
+ hprt0.b.prtconndet = 0;
+ hprt0.b.prtenchng = 0;
+ hprt0.b.prtovrcurrchng = 0;
+ return hprt0.d32;
+}
+
+/* Checks if the parameter is outside of its valid range of values */
+#define DWC_OTG_PARAM_TEST(_param_, _low_, _high_) \
+ (((_param_) < (_low_)) || \
+ ((_param_) > (_high_)))
+
+/* Parameter access functions */
+int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int valid;
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
+ printf("warning: Wrong value for otg_cap parameter\n");
+ printf("warning: otg_cap parameter must be 0, 1 or 2\n");
+ retval = -1;
+ goto out;
+ }
+
+ valid = 1;
+ switch (val) {
+ case DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE:
+ if (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ valid = 0;
+ break;
+ case DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE:
+ if ((core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
+ && (core_if->hwcfg2.b.op_mode !=
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) {
+ valid = 0;
+ }
+ break;
+ case DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE:
+ /* always valid */
+ break;
+ }
+ if (!valid) {
+ if (dwc_otg_param_initialized(core_if->core_params->otg_cap)) {
+ printf
+ ("error: %d invalid for otg_cap paremter. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (((core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE)
+ || (core_if->hwcfg2.b.op_mode ==
+ DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST)) ?
+ DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE :
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ retval = -1;
+ }
+
+ core_if->core_params->otg_cap = val;
+ out:
+ return retval;
+}
+
+int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->otg_cap;
+}
+
+int dwc_otg_set_param_opt(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for opt parameter\n");
+ return -1;
+ }
+ core_if->core_params->opt = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->opt;
+}
+
+int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for dma enable\n");
+ return -1;
+ }
+
+ if ((val == 1) && (core_if->hwcfg2.b.architecture == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->dma_enable)) {
+ printf
+ ("error: %d invalid for dma_enable paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->dma_enable = val;
+ if (val == 0) {
+ dwc_otg_set_param_dma_desc_enable(core_if, 0);
+ }
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_enable;
+}
+
+int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for dma_enable\n");
+ printf("warning: dma_desc_enable must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == 1)
+ && ((dwc_otg_get_param_dma_enable(core_if) == 0)
+ || (core_if->hwcfg4.b.desc_dma == 0))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dma_desc_enable)) {
+ printf
+ ("error: %d invalid for dma_desc_enable paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+ core_if->core_params->dma_desc_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_desc_enable;
+}
+
+int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for host_support_fs_low_power\n");
+ printf("warning: host_support_fs_low_power must be 0 or 1\n");
+ return -1;
+ }
+ core_if->core_params->host_support_fs_ls_low_power = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
+ core_if)
+{
+ return core_if->core_params->host_support_fs_ls_low_power;
+}
+
+int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for enable_dynamic_fifo\n");
+ printf("warning: enable_dynamic_fifo must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == 1) && (core_if->hwcfg2.b.dynamic_fifo == 0)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->enable_dynamic_fifo)) {
+ printf
+ ("error: %d invalid for enable_dynamic_fifo paremter. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+ core_if->core_params->enable_dynamic_fifo = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->enable_dynamic_fifo;
+}
+
+int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 32, 32768)) {
+ printf("warning: Wrong value for data_fifo_size\n");
+ printf("warning: data_fifo_size must be 32-32768\n");
+ return -1;
+ }
+
+ if (val > core_if->hwcfg3.b.dfifo_depth) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->data_fifo_size)) {
+ printf
+ ("error: %d invalid for data_fifo_size parameter. Check HW configuration.\n",
+ val);
+ }
+ val = core_if->hwcfg3.b.dfifo_depth;
+ retval = -1;
+ }
+
+ core_if->core_params->data_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->data_fifo_size;
+}
+
+int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for dev_rx_fifo_size\n");
+ printf("warning: dev_rx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_rx_fifo_size)) {
+ printf("warning: %d invalid for dev_rx_fifo_size parameter\n", val);
+ }
+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+ retval = -1;
+ }
+
+ core_if->core_params->dev_rx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_rx_fifo_size;
+}
+
+int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for dev_nperio_tx_fifo\n");
+ printf("warning: dev_nperio_tx_fifo must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dev_nperio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for dev_nperio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->dev_nperio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_nperio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_rx_fifo_size\n");
+ printf("warning: host_rx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > dwc_read_reg32(&core_if->core_global_regs->grxfsiz)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_rx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_rx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val = dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+ retval = -1;
+ }
+
+ core_if->core_params->host_rx_fifo_size = val;
+ return retval;
+
+}
+
+int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_rx_fifo_size;
+}
+
+int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_nperio_tx_fifo_size\n");
+ printf("warning: host_nperio_tx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >> 16)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_nperio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_nperio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->host_nperio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_nperio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 16, 32768)) {
+ printf("warning: Wrong value for host_perio_tx_fifo_size\n");
+ printf("warning: host_perio_tx_fifo_size must be 16-32768\n");
+ return -1;
+ }
+
+ if (val >
+ ((dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >> 16))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_perio_tx_fifo_size)) {
+ printf
+ ("error: %d invalid for host_perio_tx_fifo_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_read_reg32(&core_if->core_global_regs->hptxfsiz) >>
+ 16);
+ retval = -1;
+ }
+
+ core_if->core_params->host_perio_tx_fifo_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_perio_tx_fifo_size;
+}
+
+int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 2047, 524288)) {
+ printf("warning: Wrong value for max_transfer_size\n");
+ printf("warning: max_transfer_size must be 2047-524288\n");
+ return -1;
+ }
+
+ if (val >= (1 << (core_if->hwcfg3.b.xfer_size_cntr_width + 11))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->max_transfer_size)) {
+ printf
+ ("error: %d invalid for max_transfer_size. Check HW configuration.\n",
+ val);
+ }
+ val =
+ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 11)) -
+ 1);
+ retval = -1;
+ }
+
+ core_if->core_params->max_transfer_size = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->max_transfer_size;
+}
+
+int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 15, 511)) {
+ printf("warning: Wrong value for max_packet_count\n");
+ printf("warning: max_packet_count must be 15-511\n");
+ return -1;
+ }
+
+ if (val > (1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4))) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->max_packet_count)) {
+ printf
+ ("error: %d invalid for max_packet_count. Check HW configuration.\n",
+ val);
+ }
+ val =
+ ((1 << (core_if->hwcfg3.b.packet_size_cntr_width + 4)) - 1);
+ retval = -1;
+ }
+
+ core_if->core_params->max_packet_count = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->max_packet_count;
+}
+
+int dwc_otg_set_param_host_channels(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 1, 16)) {
+ printf("warning: Wrong value for host_channels\n");
+ printf("warning: host_channels must be 1-16\n");
+ return -1;
+ }
+
+ if (val > (core_if->hwcfg2.b.num_host_chan + 1)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->host_channels)) {
+ printf
+ ("error: %d invalid for host_channels. Check HW configurations.\n",
+ val);
+ }
+ val = (core_if->hwcfg2.b.num_host_chan + 1);
+ retval = -1;
+ }
+
+ core_if->core_params->host_channels = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_channels;
+}
+
+int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 1, 15)) {
+ printf("warning: Wrong value for dev_endpoints\n");
+ printf("warning: dev_endpoints must be 1-15\n");
+ return -1;
+ }
+
+ if (val > (core_if->hwcfg2.b.num_dev_ep)) {
+ if (dwc_otg_param_initialized
+ (core_if->core_params->dev_endpoints)) {
+ printf
+ ("error: %d invalid for dev_endpoints. Check HW configurations.\n",
+ val);
+ }
+ val = core_if->hwcfg2.b.num_dev_ep;
+ retval = -1;
+ }
+
+ core_if->core_params->dev_endpoints = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dev_endpoints;
+}
+
+int dwc_otg_set_param_phy_type(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ int valid = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 2)) {
+ printf("warning: Wrong value for phy_type\n");
+ printf("warning: phy_type must be 0, 1 or 2\n");
+ return -1;
+ }
+#ifndef NO_FS_PHY_HW_CHECKS
+ if ((val == DWC_PHY_TYPE_PARAM_UTMI) &&
+ ((core_if->hwcfg2.b.hs_phy_type == 1) ||
+ (core_if->hwcfg2.b.hs_phy_type == 3))) {
+ valid = 1;
+ } else if ((val == DWC_PHY_TYPE_PARAM_ULPI) &&
+ ((core_if->hwcfg2.b.hs_phy_type == 2) ||
+ (core_if->hwcfg2.b.hs_phy_type == 3))) {
+ valid = 1;
+ } else if ((val == DWC_PHY_TYPE_PARAM_FS) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1)) {
+ valid = 1;
+ }
+ if (!valid) {
+ if (dwc_otg_param_initialized(core_if->core_params->phy_type)) {
+ printf
+ ("error: %d invalid for phy_type. Check HW configurations.\n",
+ val);
+ }
+ if (core_if->hwcfg2.b.hs_phy_type) {
+ if ((core_if->hwcfg2.b.hs_phy_type == 3) ||
+ (core_if->hwcfg2.b.hs_phy_type == 1)) {
+ val = DWC_PHY_TYPE_PARAM_UTMI;
+ } else {
+ val = DWC_PHY_TYPE_PARAM_ULPI;
+ }
+ }
+ retval = -1;
+ }
+#endif
+ core_if->core_params->phy_type = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_type;
+}
+
+int dwc_otg_set_param_speed(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for speed parameter\n");
+ printf("warning: max_speed parameter must be 0 or 1\n");
+ return -1;
+ }
+ if ((val == 0)
+ && dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS) {
+ if (dwc_otg_param_initialized(core_if->core_params->speed)) {
+ printf
+ ("error: %d invalid for speed paremter. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_otg_get_param_phy_type(core_if) ==
+ DWC_PHY_TYPE_PARAM_FS ? 1 : 0);
+ retval = -1;
+ }
+ core_if->core_params->speed = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->speed;
+}
+
+int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf
+ ("warning: Wrong value for host_ls_low_power_phy_clk parameter\n");
+ printf("warning: host_ls_low_power_phy_clk must be 0 or 1\n");
+ return -1;
+ }
+
+ if ((val == DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ)
+ && (dwc_otg_get_param_phy_type(core_if) == DWC_PHY_TYPE_PARAM_FS)) {
+ if (dwc_otg_param_initialized(core_if->core_params->host_ls_low_power_phy_clk)) {
+ printf("error: %d invalid for host_ls_low_power_phy_clk. Check HW configuration.\n",
+ val);
+ }
+ val =
+ (dwc_otg_get_param_phy_type(core_if) ==
+ DWC_PHY_TYPE_PARAM_FS) ?
+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ :
+ DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ;
+ retval = -1;
+ }
+
+ core_if->core_params->host_ls_low_power_phy_clk = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->host_ls_low_power_phy_clk;
+}
+
+int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for phy_ulpi_ddr\n");
+ printf("warning: phy_upli_ddr must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_ulpi_ddr = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_ulpi_ddr;
+}
+
+int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for phy_ulpi_ext_vbus\n");
+ printf("warning: phy_ulpi_ext_vbus must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_ulpi_ext_vbus = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_ulpi_ext_vbus;
+}
+
+int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 8) && DWC_OTG_PARAM_TEST(val, 16, 16)) {
+ printf("warning: Wrong valaue for phy_utmi_width\n");
+ printf("warning: phy_utmi_width must be 8 or 16\n");
+ return -1;
+ }
+
+ core_if->core_params->phy_utmi_width = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->phy_utmi_width;
+}
+
+int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for ulpi_fs_ls\n");
+ printf("warning: ulpi_fs_ls must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->ulpi_fs_ls = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ulpi_fs_ls;
+}
+
+int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for ts_dline\n");
+ printf("warning: ts_dline must be 0 or 1\n");
+ return -1;
+ }
+
+ core_if->core_params->ts_dline = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ts_dline;
+}
+
+int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for i2c_enable\n");
+ printf("warning: i2c_enable must be 0 or 1\n");
+ return -1;
+ }
+#ifndef NO_FS_PHY_HW_CHECK
+ if (val == 1 && core_if->hwcfg3.b.i2c == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->i2c_enable)) {
+ printf("error: %d invalid for i2c_enable. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+#endif
+
+ core_if->core_params->i2c_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->i2c_enable;
+}
+
+int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val, int fifo_num)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
+ printf("warning: Wrong value for dev_perio_tx_fifo_size\n");
+ printf("warning: dev_perio_tx_fifo_size must be 4-768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_perio_tx_fifo_size[fifo_num])) {
+ printf("error: `%d' invalid for parameter `dev_perio_fifo_size_%d'. Check HW configuration.\n",
+ val, fifo_num);
+ }
+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
+ retval = -1;
+ }
+
+ core_if->core_params->dev_perio_tx_fifo_size[fifo_num] = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num)
+{
+ return core_if->core_params->dev_perio_tx_fifo_size[fifo_num];
+}
+
+int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong valaue for en_multiple_tx_fifo,\n");
+ printf("warning: en_multiple_tx_fifo must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val == 1 && core_if->hwcfg4.b.ded_fifo_en == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->en_multiple_tx_fifo)) {
+ printf("error: %d invalid for parameter en_multiple_tx_fifo. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->en_multiple_tx_fifo = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->en_multiple_tx_fifo;
+}
+
+int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if, int32_t val,
+ int fifo_num)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 4, 768)) {
+ printf("warning: Wrong value for dev_tx_fifo_size\n");
+ printf("warning: dev_tx_fifo_size must be 4-768\n");
+ return -1;
+ }
+
+ if (val > (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]))) {
+ if (dwc_otg_param_initialized(core_if->core_params->dev_tx_fifo_size[fifo_num])) {
+ printf("error: `%d' invalid for parameter `dev_tx_fifo_size_%d'. Check HW configuration.\n",
+ val, fifo_num);
+ }
+ val = (dwc_read_reg32(&core_if->core_global_regs->dptxfsiz_dieptxf[fifo_num]));
+ retval = -1;
+ }
+
+ core_if->core_params->dev_tx_fifo_size[fifo_num] = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num)
+{
+ return core_if->core_params->dev_tx_fifo_size[fifo_num];
+}
+
+int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 7)) {
+ printf("warning: Wrong value for thr_ctl\n");
+ printf("warning: thr_ctl must be 0-7\n");
+ return -1;
+ }
+
+ if ((val != 0) &&
+ (!dwc_otg_get_param_dma_enable(core_if) ||
+ !core_if->hwcfg4.b.ded_fifo_en)) {
+ if (dwc_otg_param_initialized(core_if->core_params->thr_ctl)) {
+ printf("error: %d invalid for parameter thr_ctl. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->thr_ctl = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_thr_ctl(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->thr_ctl;
+}
+
+int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: Wrong value for lpm_enable\n");
+ printf("warning: lpm_enable must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val && !core_if->hwcfg3.b.otg_lpm_en) {
+ if (dwc_otg_param_initialized(core_if->core_params->lpm_enable)) {
+ printf("error: %d invalid for parameter lpm_enable. Check HW configuration.\n",
+ val);
+ }
+ val = 0;
+ retval = -1;
+ }
+
+ core_if->core_params->lpm_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->lpm_enable;
+}
+
+int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
+ printf("warning: Wrong valaue for tx_thr_length\n");
+ printf("warning: tx_thr_length must be 8 - 128\n");
+ return -1;
+ }
+
+ core_if->core_params->tx_thr_length = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_tx_thr_length(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->tx_thr_length;
+}
+
+int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 8, 128)) {
+ printf("warning: Wrong valaue for rx_thr_length\n");
+ printf("warning: rx_thr_length must be 8 - 128\n");
+ return -1;
+ }
+
+ core_if->core_params->rx_thr_length = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_rx_thr_length(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->rx_thr_length;
+}
+
+int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ if (DWC_OTG_PARAM_TEST(val, 1, 1) &&
+ DWC_OTG_PARAM_TEST(val, 4, 4) &&
+ DWC_OTG_PARAM_TEST(val, 8, 8) &&
+ DWC_OTG_PARAM_TEST(val, 16, 16) &&
+ DWC_OTG_PARAM_TEST(val, 32, 32) &&
+ DWC_OTG_PARAM_TEST(val, 64, 64) &&
+ DWC_OTG_PARAM_TEST(val, 128, 128) &&
+ DWC_OTG_PARAM_TEST(val, 256, 256)) {
+ printf("warning: `%d' invalid for parameter `dma_burst_size'\n", val);
+ return -1;
+ }
+ core_if->core_params->dma_burst_size = val;
+ return 0;
+}
+
+int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->dma_burst_size;
+}
+
+int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `pti_enable'\n", val);
+ return -1;
+ }
+ if (val && (core_if->snpsid < OTG_CORE_REV_2_72a)) {
+ if (dwc_otg_param_initialized(core_if->core_params->pti_enable)) {
+ printf("error: %d invalid for parameter pti_enable. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->pti_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->pti_enable;
+}
+
+int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `mpi_enable'\n", val);
+ return -1;
+ }
+ if (val && (core_if->hwcfg2.b.multi_proc_int == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->mpi_enable)) {
+ printf("error: %d invalid for parameter mpi_enable. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->mpi_enable = val;
+ return retval;
+}
+
+int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->mpi_enable;
+}
+
+int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t *core_if,
+ int32_t val)
+{
+ int retval = 0;
+ if (DWC_OTG_PARAM_TEST(val, 0, 1)) {
+ printf("warning: `%d' invalid for parameter `ic_usb_cap'\n", val);
+ printf("warning: ic_usb_cap must be 0 or 1\n");
+ return -1;
+ }
+
+ if (val && (core_if->hwcfg3.b.otg_enable_ic_usb == 0)) {
+ if (dwc_otg_param_initialized(core_if->core_params->ic_usb_cap)) {
+ printf("error: %d invalid for parameter ic_usb_cap. Check HW configuration.\n",
+ val);
+ }
+ retval = -1;
+ val = 0;
+ }
+ core_if->core_params->ic_usb_cap = val;
+ return retval;
+}
+int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ic_usb_cap;
+}
+
+int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if, int32_t val)
+{
+ int retval = 0;
+ int valid = 1;
+
+ if (DWC_OTG_PARAM_TEST(val, 0, 3)) {
+ printf("warning: `%d' invalid for parameter `ahb_thr_ratio'\n", val);
+ printf("warning: ahb_thr_ratio must be 0 - 3\n");
+ return -1;
+ }
+
+ if (val && (core_if->snpsid < OTG_CORE_REV_2_81a || !dwc_otg_get_param_thr_ctl(core_if))) {
+ valid = 0;
+ } else if (val && ((dwc_otg_get_param_tx_thr_length(core_if) / (1 << val)) < 4)) {
+ valid = 0;
+ }
+ if (valid == 0) {
+ if (dwc_otg_param_initialized(core_if->core_params->ahb_thr_ratio)) {
+ printf("error: %d invalid for parameter ahb_thr_ratio. Chack HW configuration.\n", val);
+ }
+ retval = -1;
+ val = 0;
+ }
+
+ core_if->core_params->ahb_thr_ratio = val;
+ return retval;
+}
+int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if)
+{
+ return core_if->core_params->ahb_thr_ratio;
+}
+
+
+uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.hstnegscs;
+}
+
+uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.sesreqscs;
+}
+
+void dwc_otg_set_hnpreq(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ otgctl.b.hnpreq = val;
+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, otgctl.d32);
+}
+
+uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t *core_if)
+{
+ return core_if->snpsid;
+}
+
+uint32_t dwc_otg_get_mode(dwc_otg_core_if_t *core_if)
+{
+ gotgctl_data_t otgctl;
+ otgctl.d32 = dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+ return otgctl.b.currmod;
+}
+
+uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t *core_if)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ return usbcfg.b.hnpcap;
+}
+
+void dwc_otg_set_hnpcapable(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ usbcfg.b.hnpcap = val;
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
+}
+
+uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t *core_if)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ return usbcfg.b.srpcap;
+}
+
+void dwc_otg_set_srpcapable(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ gusbcfg_data_t usbcfg;
+ usbcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+ usbcfg.b.srpcap = val;
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, usbcfg.d32);
+}
+
+uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtconnsts;
+}
+
+uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtpwr;
+
+}
+
+void dwc_otg_set_prtpower(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtpwr = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t *core_if)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ return hprt0.b.prtsusp;
+
+}
+
+void dwc_otg_set_prtsuspend(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtsusp = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+void dwc_otg_set_prtresume(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ hprt0_data_t hprt0;
+ hprt0.d32 = dwc_read_reg32(core_if->host_if->hprt0);
+ hprt0.b.prtres = val;
+ dwc_write_reg32(core_if->host_if->hprt0, hprt0.d32);
+}
+
+uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+
+ return lpmcfg.b.prt_sleep_sts;
+}
+
+uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.rem_wkup_en;
+}
+
+uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.appl_resp;
+}
+
+void dwc_otg_set_lpmresponse(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.appl_resp = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.hsic_connect;
+}
+
+void dwc_otg_set_hsic_connect(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.hsic_connect = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t *core_if)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ return lpmcfg.b.inv_sel_hsic;
+
+}
+
+void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ glpmcfg_data_t lpmcfg;
+ lpmcfg.d32 = dwc_read_reg32(&core_if->core_global_regs->glpmcfg);
+ lpmcfg.b.inv_sel_hsic = val;
+ dwc_write_reg32(&core_if->core_global_regs->glpmcfg, lpmcfg.d32);
+}
+
+uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gotgctl);
+}
+
+void dwc_otg_set_gotgctl(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gotgctl, val);
+}
+
+uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gusbcfg);
+}
+
+void dwc_otg_set_gusbcfg(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gusbcfg, val);
+}
+
+uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->grxfsiz);
+}
+
+void dwc_otg_set_grxfsiz(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->grxfsiz, val);
+}
+
+uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gnptxfsiz);
+}
+
+void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gnptxfsiz, val);
+}
+
+uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->gpvndctl);
+}
+
+void dwc_otg_set_gpvndctl(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->gpvndctl, val);
+}
+
+uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->ggpio);
+}
+
+void dwc_otg_set_ggpio(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->ggpio, val);
+}
+
+uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(core_if->host_if->hprt0);
+
+}
+
+void dwc_otg_set_hprt0(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(core_if->host_if->hprt0, val);
+}
+
+uint32_t dwc_otg_get_guid(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->guid);
+}
+
+void dwc_otg_set_guid(dwc_otg_core_if_t *core_if, uint32_t val)
+{
+ dwc_write_reg32(&core_if->core_global_regs->guid, val);
+}
+
+uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t *core_if)
+{
+ return dwc_read_reg32(&core_if->core_global_regs->hptxfsiz);
+}
+
+
+static int dwc_otg_setup_params(dwc_otg_core_if_t *core_if)
+{
+ int i;
+ core_if->core_params = malloc(sizeof(*core_if->core_params));
+ if (!core_if->core_params) {
+ return -1;
+ }
+ dwc_otg_set_uninitialized((int32_t *) core_if->core_params,
+ sizeof(*core_if->core_params) /
+ sizeof(int32_t));
+ PDEBUG("Setting default values for core params\n");
+ dwc_otg_set_param_otg_cap(core_if, dwc_param_otg_cap_default);
+ dwc_otg_set_param_dma_enable(core_if, dwc_param_dma_enable_default);
+ dwc_otg_set_param_dma_desc_enable(core_if,
+ dwc_param_dma_desc_enable_default);
+ dwc_otg_set_param_opt(core_if, dwc_param_opt_default);
+ dwc_otg_set_param_dma_burst_size(core_if,
+ dwc_param_dma_burst_size_default);
+ dwc_otg_set_param_host_support_fs_ls_low_power(core_if,
+ dwc_param_host_support_fs_ls_low_power_default);
+ dwc_otg_set_param_enable_dynamic_fifo(core_if,
+ dwc_param_enable_dynamic_fifo_default);
+ dwc_otg_set_param_data_fifo_size(core_if,
+ dwc_param_data_fifo_size_default);
+ dwc_otg_set_param_dev_rx_fifo_size(core_if,
+ dwc_param_dev_rx_fifo_size_default);
+ dwc_otg_set_param_dev_nperio_tx_fifo_size(core_if,
+ dwc_param_dev_nperio_tx_fifo_size_default);
+ dwc_otg_set_param_host_rx_fifo_size(core_if,
+ dwc_param_host_rx_fifo_size_default);
+ dwc_otg_set_param_host_nperio_tx_fifo_size(core_if,
+ dwc_param_host_nperio_tx_fifo_size_default);
+ dwc_otg_set_param_host_perio_tx_fifo_size(core_if,
+ dwc_param_host_perio_tx_fifo_size_default);
+ dwc_otg_set_param_max_transfer_size(core_if,
+ dwc_param_max_transfer_size_default);
+ dwc_otg_set_param_max_packet_count(core_if,
+ dwc_param_max_packet_count_default);
+ dwc_otg_set_param_host_channels(core_if,
+ dwc_param_host_channels_default);
+ dwc_otg_set_param_dev_endpoints(core_if,
+ dwc_param_dev_endpoints_default);
+ dwc_otg_set_param_phy_type(core_if, dwc_param_phy_type_default);
+ dwc_otg_set_param_speed(core_if, dwc_param_speed_default);
+ dwc_otg_set_param_host_ls_low_power_phy_clk(core_if,
+ dwc_param_host_ls_low_power_phy_clk_default);
+ dwc_otg_set_param_phy_ulpi_ddr(core_if, dwc_param_phy_ulpi_ddr_default);
+ dwc_otg_set_param_phy_ulpi_ext_vbus(core_if,
+ dwc_param_phy_ulpi_ext_vbus_default);
+ dwc_otg_set_param_phy_utmi_width(core_if,
+ dwc_param_phy_utmi_width_default);
+ dwc_otg_set_param_ts_dline(core_if, dwc_param_ts_dline_default);
+ dwc_otg_set_param_i2c_enable(core_if, dwc_param_i2c_enable_default);
+ dwc_otg_set_param_ulpi_fs_ls(core_if, dwc_param_ulpi_fs_ls_default);
+ dwc_otg_set_param_en_multiple_tx_fifo(core_if,
+ dwc_param_en_multiple_tx_fifo_default);
+ for (i = 0; i < 15; i++) {
+ dwc_otg_set_param_dev_perio_tx_fifo_size(core_if,
+ dwc_param_dev_perio_tx_fifo_size_default,
+ i);
+ }
+
+ for (i = 0; i < 15; i++) {
+ dwc_otg_set_param_dev_tx_fifo_size(core_if,
+ dwc_param_dev_tx_fifo_size_default,
+ i);
+ }
+ dwc_otg_set_param_thr_ctl(core_if, dwc_param_thr_ctl_default);
+ dwc_otg_set_param_mpi_enable(core_if, dwc_param_mpi_enable_default);
+ dwc_otg_set_param_pti_enable(core_if, dwc_param_pti_enable_default);
+ dwc_otg_set_param_lpm_enable(core_if, dwc_param_lpm_enable_default);
+ dwc_otg_set_param_ic_usb_cap(core_if, dwc_param_ic_usb_cap_default);
+ dwc_otg_set_param_tx_thr_length(core_if,
+ dwc_param_tx_thr_length_default);
+ dwc_otg_set_param_rx_thr_length(core_if,
+ dwc_param_rx_thr_length_default);
+ dwc_otg_set_param_ahb_thr_ratio(core_if, dwc_param_ahb_thr_ratio_default);
+ PDEBUG("Finished setting default values for core params\n");
+ return 0;
+}
+
+void dwc_otg_cil_init(dwc_otg_core_if_t *core_if, const uint32_t *reg_base_addr)
+{
+ dwc_otg_host_if_t *host_if = 0;
+ uint8_t *reg_base = (uint8_t *) reg_base_addr;
+ int i = 0;
+
+ PDEBUG("%s(%p)\n", __func__, reg_base_addr);
+
+ if (core_if == 0) {
+ PDEBUG("dwc_otg_core_if_t is NULL\n");
+ return;
+ }
+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+ /*
+ * Allocate the Host Mode structures.
+ */
+ host_if = malloc(sizeof(dwc_otg_host_if_t));
+
+ if (host_if == 0) {
+ PDEBUG("Allocation of dwc_otg_host_if_t failed\n");
+ return;
+ }
+
+ host_if->host_global_regs = (dwc_otg_host_global_regs_t *)
+ (reg_base + DWC_OTG_HOST_GLOBAL_REG_OFFSET);
+
+ host_if->hprt0 =
+ (uint32_t *) (reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ host_if->hc_regs[i] = (dwc_otg_hc_regs_t *)
+ (reg_base + DWC_OTG_HOST_CHAN_REGS_OFFSET +
+ (i * DWC_OTG_CHAN_REGS_OFFSET));
+ PDEBUG("hc_reg[%d]->hcchar=%p\n",
+ i, &host_if->hc_regs[i]->hcchar);
+ }
+
+ host_if->num_host_channels = MAX_EPS_CHANNELS;
+ core_if->host_if = host_if;
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++) {
+ core_if->data_fifo[i] =
+ (uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +
+ (i * DWC_OTG_DATA_FIFO_SIZE));
+ PDEBUG("data_fifo[%d]=0x%08x\n",
+ i, (unsigned)core_if->data_fifo[i]);
+ }
+
+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ /*
+ * Store the contents of the hardware configuration registers here for
+ * easy access later.
+ */
+ core_if->hwcfg1.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg1);
+ core_if->hwcfg2.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg2);
+ core_if->hwcfg3.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg3);
+ core_if->hwcfg4.d32 =
+ dwc_read_reg32(&core_if->core_global_regs->ghwcfg4);
+
+ PDEBUG("hwcfg1=%08x\n", core_if->hwcfg1.d32);
+ PDEBUG("hwcfg2=%08x\n", core_if->hwcfg2.d32);
+ PDEBUG("hwcfg3=%08x\n", core_if->hwcfg3.d32);
+ PDEBUG("hwcfg4=%08x\n", core_if->hwcfg4.d32);
+
+ core_if->hcfg.d32 =
+ dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
+
+ PDEBUG("hcfg=%08x\n", core_if->hcfg.d32);
+ PDEBUG("dcfg=%08x\n", core_if->dcfg.d32);
+
+ PDEBUG("op_mode=%0x\n", core_if->hwcfg2.b.op_mode);
+ PDEBUG("arch=%0x\n", core_if->hwcfg2.b.architecture);
+ PDEBUG("num_dev_ep=%d\n", core_if->hwcfg2.b.num_dev_ep);
+ PDEBUG("num_host_chan=%d\n",
+ core_if->hwcfg2.b.num_host_chan);
+ PDEBUG("nonperio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.nonperio_tx_q_depth);
+ PDEBUG("host_perio_tx_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.host_perio_tx_q_depth);
+ PDEBUG("dev_token_q_depth=0x%0x\n",
+ core_if->hwcfg2.b.dev_token_q_depth);
+
+ PDEBUG("Total FIFO SZ=%d\n",
+ core_if->hwcfg3.b.dfifo_depth);
+ PDEBUG("xfer_size_cntr_width=%0x\n",
+ core_if->hwcfg3.b.xfer_size_cntr_width);
+
+ core_if->snpsid = dwc_read_reg32(&core_if->core_global_regs->gsnpsid);
+
+ printf("Core Release: %x.%x%x%x\n",
+ (core_if->snpsid >> 12 & 0xF),
+ (core_if->snpsid >> 8 & 0xF),
+ (core_if->snpsid >> 4 & 0xF), (core_if->snpsid & 0xF));
+
+ dwc_otg_setup_params(core_if);
+}
+
+/**
+ * Initializes the FSLSPClkSel field of the HCFG register depending on the PHY
+ * type.
+ */
+static void init_fslspclksel(dwc_otg_core_if_t *core_if)
+{
+ uint32_t val;
+ hcfg_data_t hcfg;
+
+ if (((core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (core_if->core_params->ulpi_fs_ls)) ||
+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* Full speed PHY */
+ val = DWC_HCFG_48_MHZ;
+ } else {
+ /* High speed PHY running at full speed or high speed */
+ val = DWC_HCFG_30_60_MHZ;
+ }
+
+ PDEBUG("Initializing HCFG.FSLSPClkSel to 0x%1x\n", val);
+ hcfg.d32 = dwc_read_reg32(&core_if->host_if->host_global_regs->hcfg);
+ hcfg.b.fslspclksel = val;
+ dwc_write_reg32(&core_if->host_if->host_global_regs->hcfg, hcfg.d32);
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_flush_tx_fifo(dwc_otg_core_if_t *core_if, const int num)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("Flush Tx FIFO %d\n", num);
+
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = num;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 10000) {
+ printf("%s() HANG! GRSTCTL=%0x GNPTXSTS=0x%08x\n",
+ __func__, greset.d32,
+ dwc_read_reg32(&global_regs->gnptxsts));
+ break;
+ }
+ udelay(1);
+ } while (greset.b.txfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_flush_rx_fifo(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("%s\n", __func__);
+ /*
+ *
+ */
+ greset.b.rxfflsh = 1;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 10000) {
+ printf("%s() HANG! GRSTCTL=%0x\n", __func__,
+ greset.d32);
+ break;
+ }
+ udelay(1);
+ } while (greset.b.rxfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(1);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * host mode.
+ *
+ * This function flushes the Tx and Rx FIFOs and it flushes any entries in the
+ * request queues. Host channels are reset to ensure that they are ready for
+ * performing transfers.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_core_host_init(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ dwc_otg_host_if_t *host_if = core_if->host_if;
+ dwc_otg_core_params_t *params = core_if->core_params;
+ hprt0_data_t hprt0 = {.d32 = 0 };
+ fifosize_data_t nptxfifosize;
+ fifosize_data_t ptxfifosize;
+ int i;
+ hcchar_data_t hcchar;
+ hcfg_data_t hcfg;
+ dwc_otg_hc_regs_t *hc_regs;
+ int num_channels;
+ gotgctl_data_t gotgctl = {.d32 = 0 };
+
+ PDEBUG("%s(%p)\n", __func__, core_if);
+
+ /* Restart the Phy Clock */
+ dwc_write_reg32(core_if->pcgcctl, 0);
+
+ /* Initialize Host Configuration Register */
+ init_fslspclksel(core_if);
+ if (core_if->core_params->speed == DWC_SPEED_PARAM_FULL) {
+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
+ hcfg.b.fslssupp = 1;
+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
+
+ }
+
+ if (core_if->core_params->dma_desc_enable) {
+ uint8_t op_mode = core_if->hwcfg2.b.op_mode;
+ if (!(core_if->hwcfg4.b.desc_dma && (core_if->snpsid >= OTG_CORE_REV_2_90a) &&
+ ((op_mode == DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST) ||
+ (op_mode == DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST)))) {
+
+ printf("Host can't operate in Descriptor DMA mode.\n"
+ "Either core version is below 2.90a or "
+ "GHWCFG2, GHWCFG4 registers' values do not allow Descriptor DMA in host mode.\n"
+ "To run the driver in Buffer DMA host mode set dma_desc_enable "
+ "module parameter to 0.\n");
+ return;
+ }
+ hcfg.d32 = dwc_read_reg32(&host_if->host_global_regs->hcfg);
+ hcfg.b.descdma = 1;
+ dwc_write_reg32(&host_if->host_global_regs->hcfg, hcfg.d32);
+ }
+
+ /* Configure data FIFO sizes */
+ if (core_if->hwcfg2.b.dynamic_fifo && params->enable_dynamic_fifo) {
+ PDEBUG("Total FIFO Size=%d\n",
+ core_if->total_fifo_size);
+ PDEBUG("Rx FIFO Size=%d\n",
+ params->host_rx_fifo_size);
+ PDEBUG("NP Tx FIFO Size=%d\n",
+ params->host_nperio_tx_fifo_size);
+ PDEBUG("P Tx FIFO Size=%d\n",
+ params->host_perio_tx_fifo_size);
+
+ /* Rx FIFO */
+ PDEBUG("initial grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+ dwc_write_reg32(&global_regs->grxfsiz,
+ params->host_rx_fifo_size);
+ PDEBUG("new grxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->grxfsiz));
+
+ /* Non-periodic Tx FIFO */
+ PDEBUG("initial gnptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->gnptxfsiz));
+ nptxfifosize.b.depth = params->host_nperio_tx_fifo_size;
+ nptxfifosize.b.startaddr = params->host_rx_fifo_size;
+ dwc_write_reg32(&global_regs->gnptxfsiz, nptxfifosize.d32);
+ PDEBUG("new gnptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->gnptxfsiz));
+
+ /* Periodic Tx FIFO */
+ PDEBUG("initial hptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->hptxfsiz));
+ ptxfifosize.b.depth = params->host_perio_tx_fifo_size;
+ ptxfifosize.b.startaddr =
+ nptxfifosize.b.startaddr + nptxfifosize.b.depth;
+ dwc_write_reg32(&global_regs->hptxfsiz, ptxfifosize.d32);
+ PDEBUG("new hptxfsiz=%08x\n",
+ dwc_read_reg32(&global_regs->hptxfsiz));
+ }
+
+ /* Clear Host Set HNP Enable in the OTG Control Register */
+ gotgctl.b.hstsethnpen = 1;
+ dwc_modify_reg32(&global_regs->gotgctl, gotgctl.d32, 0);
+
+ /* Make sure the FIFOs are flushed. */
+ dwc_otg_flush_tx_fifo(core_if, 0x10 /* all Tx FIFOs */);
+ dwc_otg_flush_rx_fifo(core_if);
+
+ if (!core_if->core_params->dma_desc_enable) {
+ /* Flush out any leftover queued requests. */
+ num_channels = core_if->core_params->host_channels;
+
+ for (i = 0; i < num_channels; i++) {
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.chen = 0;
+ hcchar.b.chdis = 1;
+ hcchar.b.epdir = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+ }
+
+ /* Halt all channels to put them into a known state. */
+ for (i = 0; i < num_channels; i++) {
+ int count = 0;
+ hc_regs = core_if->host_if->hc_regs[i];
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ hcchar.b.chen = 1;
+ hcchar.b.chdis = 1;
+ hcchar.b.epdir = 0;
+ dwc_write_reg32(&hc_regs->hcchar, hcchar.d32);
+ PDEBUG("%s: Halt channel %d regs %p\n", __func__, i, hc_regs);
+ do {
+ hcchar.d32 = dwc_read_reg32(&hc_regs->hcchar);
+ if (++count > 1000) {
+ printf
+ ("%s: Unable to clear halt on channel %d (timeout HCCHAR 0x%X @%p)\n",
+ __func__, i, hcchar.d32, &hc_regs->hcchar);
+ break;
+ }
+ udelay(1);
+ } while (hcchar.b.chen);
+ }
+ }
+
+ /* Turn on the vbus power. */
+ PDEBUG("Init: Port Power? op_state=%d\n", core_if->op_state);
+ if (core_if->op_state == A_HOST) {
+ hprt0.d32 = dwc_otg_read_hprt0(core_if);
+ PDEBUG("Init: Power Port (%d, %08x)\n", hprt0.b.prtpwr, hprt0.d32);
+ if (hprt0.b.prtpwr == 0) {
+ hprt0.b.prtpwr = 1;
+ dwc_write_reg32(host_if->hprt0, hprt0.d32);
+ }
+ }
+}
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_core_reset(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset = {.d32 = 0 };
+ int count = 0;
+
+ PDEBUG("%s\n", __func__);
+ /* Wait for AHB master IDLE state. */
+ do {
+ udelay(10);
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 100000) {
+ printf("%s() HANG! AHB Idle GRSTCTL=%0x\n", __func__,
+ greset.d32);
+ return;
+ }
+ } while (greset.b.ahbidle == 0);
+
+ /* Core Soft Reset */
+ count = 0;
+ greset.b.csftrst = 1;
+ dwc_write_reg32(&global_regs->grstctl, greset.d32);
+ do {
+ greset.d32 = dwc_read_reg32(&global_regs->grstctl);
+ if (++count > 1000000) {
+ printf("%s() HANG! Soft Reset GRSTCTL=%0x\n",
+ __func__, greset.d32);
+ break;
+ }
+ udelay(1);
+ } while (greset.b.csftrst == 1);
+
+ /* Wait for 3 PHY Clocks */
+ udelay(100 * 1000);
+}
+
+
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_core_init(dwc_otg_core_if_t *core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ gahbcfg_data_t ahbcfg = {.d32 = 0 };
+ gusbcfg_data_t usbcfg = {.d32 = 0 };
+ gi2cctl_data_t i2cctl = {.d32 = 0 };
+
+ PDEBUG("dwc_otg_core_init(%p) regs at %p\n",
+ core_if, global_regs);
+
+ /* Common Initialization */
+
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+
+ /* Program the ULPI External VBUS bit if needed */
+ usbcfg.b.ulpi_ext_vbus_drv =
+ (core_if->core_params->phy_ulpi_ext_vbus ==
+ DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+ /* Set external TS Dline pulsing */
+ usbcfg.b.term_sel_dl_pulse =
+ (core_if->core_params->ts_dline == 1) ? 1 : 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset the Controller */
+ dwc_otg_core_reset(core_if);
+
+ /* Initialize parameters from Hardware configuration registers. */
+ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
+ core_if->rx_fifo_size = dwc_read_reg32(&global_regs->grxfsiz);
+ core_if->nperio_tx_fifo_size =
+ dwc_read_reg32(&global_regs->gnptxfsiz) >> 16;
+
+ PDEBUG("Total FIFO SZ=%d\n", core_if->total_fifo_size);
+ PDEBUG("Rx FIFO SZ=%d\n", core_if->rx_fifo_size);
+ PDEBUG("NP Tx FIFO SZ=%d\n",
+ core_if->nperio_tx_fifo_size);
+
+ /* This programming sequence needs to happen in FS mode before any other
+ * programming occurs */
+ if ((core_if->core_params->speed == DWC_SPEED_PARAM_FULL) &&
+ (core_if->core_params->phy_type == DWC_PHY_TYPE_PARAM_FS)) {
+ /* If FS mode with FS PHY */
+
+ /* core_init() is now called on every switch so only call the
+ * following for the first time through. */
+ if (!core_if->phy_init_done) {
+ core_if->phy_init_done = 1;
+ PDEBUG("FS_PHY detected\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.physel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Reset after a PHY select */
+ dwc_otg_core_reset(core_if);
+ }
+
+ /* Program DCFG.DevSpd or HCFG.FSLSPclkSel to 48Mhz in FS. Also
+ * do this on HNP Dev/Host mode switches (done in dev_init and
+ * host_init). */
+ if (dwc_otg_is_host_mode(core_if)) {
+ init_fslspclksel(core_if);
+ }
+
+ if (core_if->core_params->i2c_enable) {
+ PDEBUG("FS_PHY Enabling I2c\n");
+ /* Program GUSBCFG.OtgUtmifsSel to I2C */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.otgutmifssel = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ /* Program GI2CCTL.I2CEn */
+ i2cctl.d32 = dwc_read_reg32(&global_regs->gi2cctl);
+ i2cctl.b.i2cdevaddr = 1;
+ i2cctl.b.i2cen = 0;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ i2cctl.b.i2cen = 1;
+ dwc_write_reg32(&global_regs->gi2cctl, i2cctl.d32);
+ }
+
+ } /* endif speed == DWC_SPEED_PARAM_FULL */
+ else {
+ /* High speed PHY. */
+ if (!core_if->phy_init_done) {
+ core_if->phy_init_done = 1;
+ /* HS PHY parameters. These parameters are preserved
+ * during soft reset so only program the first time. Do
+ * a soft reset immediately after setting phyif. */
+ usbcfg.b.ulpi_utmi_sel = core_if->core_params->phy_type;
+ if (usbcfg.b.ulpi_utmi_sel == 1) {
+ PDEBUG(" ULPI interface \n");
+ /* ULPI interface */
+ usbcfg.b.phyif = 0;
+ usbcfg.b.ddrsel =
+ core_if->core_params->phy_ulpi_ddr;
+ } else {
+ PDEBUG(" UTMI+ interface \n");
+ /* UTMI+ interface */
+ if (core_if->core_params->phy_utmi_width == 16) {
+ usbcfg.b.phyif = 1;
+
+ } else {
+ usbcfg.b.phyif = 0;
+ }
+
+ }
+
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ /* Reset after setting the PHY parameters */
+ dwc_otg_core_reset(core_if);
+ }
+ }
+
+ if ((core_if->hwcfg2.b.hs_phy_type == 2) &&
+ (core_if->hwcfg2.b.fs_phy_type == 1) &&
+ (core_if->core_params->ulpi_fs_ls)) {
+ PDEBUG("Setting ULPI FSLS\n");
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 1;
+ usbcfg.b.ulpi_clk_sus_m = 1;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ } else {
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 0;
+ usbcfg.b.ulpi_clk_sus_m = 0;
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+
+ /* Program the GAHBCFG Register. */
+ switch (core_if->hwcfg2.b.architecture) {
+
+ case DWC_SLAVE_ONLY_ARCH:
+ PDEBUG("Slave Only Mode\n");
+ ahbcfg.b.nptxfemplvl_txfemplvl =
+ DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ core_if->dma_enable = 0;
+ core_if->dma_desc_enable = 0;
+ break;
+
+ case DWC_EXT_DMA_ARCH:
+ PDEBUG("External DMA Mode\n");
+ {
+ uint8_t brst_sz = core_if->core_params->dma_burst_size;
+ ahbcfg.b.hburstlen = 0;
+ while (brst_sz > 1) {
+ ahbcfg.b.hburstlen++;
+ brst_sz >>= 1;
+ }
+ }
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable =
+ (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ case DWC_INT_DMA_ARCH:
+ PDEBUG("Internal DMA Mode\n");
+ /*ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR; */
+ ahbcfg.b.hburstlen = (1<<3)|(0<<0); /* WRESP=1, max 4 beats */
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable =
+ (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ }
+ if (core_if->dma_enable) {
+ if (core_if->dma_desc_enable) {
+ PDEBUG("Using Descriptor DMA mode\n");
+ } else {
+ PDEBUG("Using Buffer DMA mode\n");
+
+ }
+ } else {
+ PDEBUG("Using Slave mode\n");
+ core_if->dma_desc_enable = 0;
+ }
+
+ ahbcfg.b.dmaenable = core_if->dma_enable;
+ PDEBUG("DMA enable: %d(%08x)\n", ahbcfg.b.dmaenable, ahbcfg.d32);
+ dwc_write_reg32(&global_regs->gahbcfg, ahbcfg.d32);
+
+ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+ core_if->multiproc_int_enable = core_if->core_params->mpi_enable;
+ PDEBUG("Periodic Transfer Interrupt Enhancement - %s\n",
+ ((core_if->pti_enh_enable) ? "enabled" : "disabled"));
+ PDEBUG("Multiprocessor Interrupt Enhancement - %s\n",
+ ((core_if->multiproc_int_enable) ? "enabled" : "disabled"));
+
+
+ ahbcfg.d32 = dwc_read_reg32(&global_regs->gahbcfg);
+
+ /*
+ * Program the GUSBCFG register.
+ */
+ usbcfg.d32 = dwc_read_reg32(&global_regs->gusbcfg);
+
+ switch (core_if->hwcfg2.b.op_mode) {
+ case DWC_MODE_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = (core_if->core_params->otg_cap ==
+ DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE);
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_SRP_ONLY_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_HNP_SRP_CAPABLE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+
+ case DWC_MODE_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_SRP_CAPABLE_DEVICE:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+
+ case DWC_MODE_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = (core_if->core_params->otg_cap !=
+ DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE);
+ break;
+
+ case DWC_MODE_NO_SRP_CAPABLE_HOST:
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+ break;
+ }
+
+ dwc_write_reg32(&global_regs->gusbcfg, usbcfg.d32);
+
+ if (core_if->core_params->ic_usb_cap) {
+ gusbcfg_data_t gusbcfg = {.d32 = 0 };
+ gusbcfg.b.ic_usb_cap = 1;
+ dwc_modify_reg32(&core_if->core_global_regs->gusbcfg,
+ 0, gusbcfg.d32);
+ }
+
+ /* Do device or host intialization based on mode during PCD
+ * and HCD initialization */
+ if (dwc_otg_is_host_mode(core_if)) {
+ PDEBUG("Host Mode\n");
+ core_if->op_state = A_HOST;
+ }
+}
+
+/**
+ * Prepares a host channel for transferring packets to/from a specific
+ * endpoint. The HCCHARn register is set up with the characteristics specified
+ * in _hc. Host channel interrupts that may need to be serviced while this
+ * transfer is in progress are enabled.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ * @param hc Information needed to initialize the host channel
+ */
+void dwc_otg_hc_init(dwc_otg_core_if_t *core_if, uint8_t hc_num,
+ uint8_t dev_addr, uint8_t ep_num, uint8_t ep_is_in,
+ uint8_t ep_type, uint16_t max_packet)
+{
+ hcintmsk_data_t hc_intr_mask;
+ hcchar_data_t hcchar;
+ hcsplt_data_t hcsplt;
+
+ dwc_otg_host_if_t *host_if = core_if->host_if;
+ dwc_otg_hc_regs_t *hc_regs = host_if->hc_regs[hc_num];
+
+ /* Clear old interrupt conditions for this host channel. */
+ hc_intr_mask.d32 = 0xFFFFFFFF;
+ hc_intr_mask.b.reserved14_31 = 0;
+ dwc_write_reg32(&hc_regs->hcint, hc_intr_mask.d32);
+
+ /*
+ * Program the HCCHARn register with the endpoint characteristics for
+ * the current transfer.
+ */
+ hcchar.d32 = 0;
+ hcchar.b.devaddr = dev_addr;
+ hcchar.b.epnum = ep_num;
+ hcchar.b.epdir = ep_is_in;
+ hcchar.b.lspddev = 0; /* XXX: low speed handler needed */
+ hcchar.b.eptype = ep_type;
+ hcchar.b.mps = max_packet;
+
+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcchar, hcchar.d32);
+
+ PDEBUG("%s: Channel %d\n", __func__, hc_num);
+ PDEBUG(" Dev Addr: %d\n", hcchar.b.devaddr);
+ PDEBUG(" Ep Num: %d\n", hcchar.b.epnum);
+ PDEBUG(" Is In: %d\n", hcchar.b.epdir);
+ PDEBUG(" Is Low Speed: %d\n", hcchar.b.lspddev);
+ PDEBUG(" Ep Type: %d\n", hcchar.b.eptype);
+ PDEBUG(" Max Pkt: %d\n", hcchar.b.mps);
+ PDEBUG(" Multi Cnt: %d\n", hcchar.b.multicnt);
+
+ /*
+ * Program the HCSPLIT register for SPLITs
+ */
+ hcsplt.d32 = 0;
+ dwc_write_reg32(&host_if->hc_regs[hc_num]->hcsplt, hcsplt.d32);
+}
diff --git a/drivers/usb/host/dwc2_otg.h b/drivers/usb/host/dwc2_otg.h
new file mode 100644
index 0000000..3974e1d
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2012 Oleksandr Tymoshenko <gonzo at freebsd.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#ifndef __DWC_OTG_H__
+#define __DWC_OTG_H__
+
+/* USB HUB CONSTANTS (not OHCI-specific; see hub.h, based on usb_ohci.h) */
+
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS 0x00000001 /* current connect status */
+#define RH_PS_PES 0x00000002 /* port enable status */
+#define RH_PS_PSS 0x00000004 /* port suspend status */
+#define RH_PS_POCI 0x00000008 /* port over current indicator */
+#define RH_PS_PRS 0x00000010 /* port reset status */
+#define RH_PS_PPS 0x00000100 /* port power status */
+#define RH_PS_LSDA 0x00000200 /* low speed device attached */
+#define RH_PS_CSC 0x00010000 /* connect status change */
+#define RH_PS_PESC 0x00020000 /* port enable status change */
+#define RH_PS_PSSC 0x00040000 /* port suspend status change */
+#define RH_PS_OCIC 0x00080000 /* over current indicator change */
+#define RH_PS_PRSC 0x00100000 /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS 0x00000001 /* local power status */
+#define RH_HS_OCI 0x00000002 /* over current indicator */
+#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */
+#define RH_HS_LPSC 0x00010000 /* local power status change */
+#define RH_HS_OCIC 0x00020000 /* over current indicator change */
+#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR 0x0000ffff /* device removable flags */
+#define RH_B_PPCM 0xffff0000 /* port power control mask */
+
+/* roothub.a masks */
+#define RH_A_NDP (0xff << 0) /* number of downstream ports */
+#define RH_A_PSM (1 << 8) /* power switching mode */
+#define RH_A_NPS (1 << 9) /* no power switching */
+#define RH_A_DT (1 << 10) /* device type (mbz) */
+#define RH_A_OCPM (1 << 11) /* over current protection mode */
+#define RH_A_NOCP (1 << 12) /* no over current protection */
+#define RH_A_POTPGT (0xff << 24) /* power on to power good time */
+
+#define DWC_OTG_HC_PID_DATA0 0
+#define DWC_OTG_HC_PID_DATA2 1
+#define DWC_OTG_HC_PID_DATA1 2
+#define DWC_OTG_HC_PID_MDATA 3
+#define DWC_OTG_HC_PID_SETUP 3
+
+/** Macros defined for DWC OTG HW Release verison */
+#define OTG_CORE_REV_2_60a 0x4F54260A
+#define OTG_CORE_REV_2_71a 0x4F54271A
+#define OTG_CORE_REV_2_72a 0x4F54272A
+#define OTG_CORE_REV_2_80a 0x4F54280A
+#define OTG_CORE_REV_2_81a 0x4F54281A
+#define OTG_CORE_REV_2_90a 0x4F54290A
+
+#define DWC_OTG_EP_TYPE_CONTROL 0
+#define DWC_OTG_EP_TYPE_ISOC 1
+#define DWC_OTG_EP_TYPE_BULK 2
+#define DWC_OTG_EP_TYPE_INTR 3
+
+#define DWC_OTG_EP_SPEED_LOW 0
+#define DWC_OTG_EP_SPEED_FULL 1
+#define DWC_OTG_EP_SPEED_HIGH 2
+
+/** Maximum number of Periodic FIFOs */
+#define MAX_PERIO_FIFOS 15
+/** Maximum number of Periodic FIFOs */
+#define MAX_TX_FIFOS 15
+
+/** Maximum number of Endpoints/HostChannels */
+#define MAX_EPS_CHANNELS 16
+
+#endif /* __DWC_OTG_H__ */
diff --git a/drivers/usb/host/dwc2_otg_core_if.h b/drivers/usb/host/dwc2_otg_core_if.h
new file mode 100644
index 0000000..ee85fe5
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg_core_if.h
@@ -0,0 +1,1001 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_core_if.h $
+ * $Revision: #4 $
+ * $Date: 2008/12/18 $
+ * $Change: 1155299 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_CORE_IF_H__
+#define __DWC_CORE_IF_H__
+
+/** @file
+ * This file defines DWC_OTG Core API
+ */
+
+/**
+ * The following parameters may be specified when starting the module. These
+ * parameters define how the DWC_otg controller should be configured.
+ */
+typedef struct dwc_otg_core_params {
+ int32_t opt;
+
+ /**
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+ int32_t otg_cap;
+
+ /**
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+ int32_t dma_enable;
+
+ /**
+ * When DMA mode is enabled specifies whether to use address DMA or DMA Descritor mode for accessing the data
+ * FIFOs in device mode. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - address DMA
+ * 1 - DMA Descriptor(default, if available)
+ */
+ int32_t dma_desc_enable;
+ /** The DMA Burst size (applicable only for External DMA
+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
+ */
+ int32_t dma_burst_size; /* Translate this to GAHBCFG values */
+
+ /**
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+ int32_t speed;
+ /** Specifies whether low power mode is supported when attached
+ * to a Full Speed or Low Speed device in host mode.
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+ int32_t host_support_fs_ls_low_power;
+
+ /** Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+ int32_t host_ls_low_power_phy_clk;
+
+ /**
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+ int32_t enable_dynamic_fifo;
+
+ /** Total number of 4-byte words in the data FIFO memory. This
+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
+ * Tx FIFOs.
+ * 32 to 32768 (default 8192)
+ * Note: The total FIFO memory depth in the FPGA configuration is 8192.
+ */
+ int32_t data_fifo_size;
+
+ /** Number of 4-byte words in the Rx FIFO in device mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1064)
+ */
+ int32_t dev_rx_fifo_size;
+
+ /** Number of 4-byte words in the non-periodic Tx FIFO in device mode
+ * when dynamic FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t dev_nperio_tx_fifo_size;
+
+ /** Number of 4-byte words in each of the periodic Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
+
+ /** Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_rx_fifo_size;
+
+ /** Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_nperio_tx_fifo_size;
+
+ /** Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+ int32_t host_perio_tx_fifo_size;
+
+ /** The maximum transfer size supported in bytes.
+ * 2047 to 65535 (default 65535)
+ */
+ int32_t max_transfer_size;
+
+ /** The maximum number of packets in a transfer.
+ * 15 to 511 (default 511)
+ */
+ int32_t max_packet_count;
+
+ /** The number of host channel registers to use.
+ * 1 to 16 (default 12)
+ * Note: The FPGA configuration supports a maximum of 12 host channels.
+ */
+ int32_t host_channels;
+
+ /** The number of endpoints in addition to EP0 available for device
+ * mode operations.
+ * 1 to 15 (default 6 IN and OUT)
+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT
+ * endpoints in addition to EP0.
+ */
+ int32_t dev_endpoints;
+
+ /**
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+ int32_t phy_type;
+
+ /**
+ * Specifies the UTMI+ Data Width. This parameter is
+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+ * PHY_TYPE, this parameter indicates the data width between
+ * the MAC and the ULPI Wrapper.) Also, this parameter is
+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+ * to "8 and 16 bits", meaning that the core has been
+ * configured to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+ int32_t phy_utmi_width;
+
+ /**
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+ int32_t phy_ulpi_ddr;
+
+ /**
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+ int32_t phy_ulpi_ext_vbus;
+
+ /**
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+ int32_t i2c_enable;
+
+ int32_t ulpi_fs_ls;
+
+ int32_t ts_dline;
+
+ /**
+ * Specifies whether dedicated transmit FIFOs are
+ * enabled for non periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+ int32_t en_multiple_tx_fifo;
+
+ /** Number of 4-byte words in each of the Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
+
+ /** Thresholding enable flag-
+ * bit 0 - enable non-ISO Tx thresholding
+ * bit 1 - enable ISO Tx thresholding
+ * bit 2 - enable Rx thresholding
+ */
+ uint32_t thr_ctl;
+
+ /** Thresholding length for Tx
+ * FIFOs in 32 bit DWORDs
+ */
+ uint32_t tx_thr_length;
+
+ /** Thresholding length for Rx
+ * FIFOs in 32 bit DWORDs
+ */
+ uint32_t rx_thr_length;
+
+ /**
+ * Specifies whether LPM (Link Power Management) support is enabled
+ */
+ int32_t lpm_enable;
+
+ /** Per Transfer Interrupt
+ * mode enable flag
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t pti_enable;
+
+ /** Multi Processor Interrupt
+ * mode enable flag
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t mpi_enable;
+
+ /** IS_USB Capability
+ * 1 - Enabled
+ * 0 - Disabled
+ */
+ int32_t ic_usb_cap;
+
+ /** AHB Threshold Ratio
+ * 2'b00 AHB Threshold = MAC Threshold
+ * 2'b01 AHB Threshold = 1/2 MAC Threshold
+ * 2'b10 AHB Threshold = 1/4 MAC Threshold
+ * 2'b11 AHB Threshold = 1/8 MAC Threshold
+ */
+ int32_t ahb_thr_ratio;
+
+} dwc_otg_core_params_t;
+
+/**
+ * The <code>dwc_otg_core_if</code> structure contains information needed to manage
+ * the DWC_otg controller acting in either host or device mode. It
+ * represents the programming view of the controller as a whole.
+ */
+struct dwc_otg_core_if {
+ /** Parameters that define how the core should be configured.*/
+ dwc_otg_core_params_t *core_params;
+
+ /** Core Global registers starting at offset 000h. */
+ dwc_otg_core_global_regs_t *core_global_regs;
+
+ /** Host-specific information */
+ dwc_otg_host_if_t *host_if;
+
+ /** Value from SNPSID register */
+ uint32_t snpsid;
+
+ /*
+ * Set to 1 if the core PHY interface bits in USBCFG have been
+ * initialized.
+ */
+ uint8_t phy_init_done;
+
+ /* Common configuration information */
+ /** Power and Clock Gating Control Register */
+ volatile uint32_t *pcgcctl;
+#define DWC_OTG_PCGCCTL_OFFSET 0xE00
+
+ /** Push/pop addresses for endpoints or host channels.*/
+ uint32_t *data_fifo[MAX_EPS_CHANNELS];
+#define DWC_OTG_DATA_FIFO_OFFSET 0x1000
+#define DWC_OTG_DATA_FIFO_SIZE 0x1000
+
+ /** Total RAM for FIFOs (Bytes) */
+ uint16_t total_fifo_size;
+ /** Size of Rx FIFO (Bytes) */
+ uint16_t rx_fifo_size;
+ /** Size of Non-periodic Tx FIFO (Bytes) */
+ uint16_t nperio_tx_fifo_size;
+
+ /** 1 if DMA is enabled, 0 otherwise. */
+ uint8_t dma_enable;
+
+ /** 1 if DMA descriptor is enabled, 0 otherwise. */
+ uint8_t dma_desc_enable;
+
+ /** 1 if PTI Enhancement mode is enabled, 0 otherwise. */
+ uint8_t pti_enh_enable;
+
+ /** 1 if MPI Enhancement mode is enabled, 0 otherwise. */
+ uint8_t multiproc_int_enable;
+
+ /** 1 if dedicated Tx FIFOs are enabled, 0 otherwise. */
+ uint8_t en_multiple_tx_fifo;
+
+ /** Set to 1 if multiple packets of a high-bandwidth transfer is in
+ * process of being queued */
+ uint8_t queuing_high_bandwidth;
+
+ /** Hardware Configuration -- stored here for convenience.*/
+ hwcfg1_data_t hwcfg1;
+ hwcfg2_data_t hwcfg2;
+ hwcfg3_data_t hwcfg3;
+ hwcfg4_data_t hwcfg4;
+
+ /** Host and Device Configuration -- stored here for convenience.*/
+ hcfg_data_t hcfg;
+
+ /** The operational State, during transations
+ * (a_host>>a_peripherial and b_device=>b_host) this may not
+ * match the core but allows the software to determine
+ * transitions.
+ */
+ uint8_t op_state;
+
+ /**
+ * Set to 1 if the HCD needs to be restarted on a session request
+ * interrupt. This is required if no connector ID status change has
+ * occurred since the HCD was last disconnected.
+ */
+ uint8_t restart_hcd_on_session_req;
+
+ /** HCD callbacks */
+ /** A-Device is a_host */
+#define A_HOST (1)
+ /** A-Device is a_suspend */
+#define A_SUSPEND (2)
+ /** A-Device is a_peripherial */
+#define A_PERIPHERAL (3)
+ /** B-Device is operating as a Peripheral. */
+#define B_PERIPHERAL (4)
+ /** B-Device is operating as a Host. */
+#define B_HOST (5)
+
+ /** Device mode Periodic Tx FIFO Mask */
+ uint32_t p_tx_msk;
+ /** Device mode Periodic Tx FIFO Mask */
+ uint32_t tx_msk;
+};
+
+typedef struct dwc_otg_core_if dwc_otg_core_if_t;
+
+extern void dwc_otg_cil_init(dwc_otg_core_if_t *_core_if, const uint32_t *_reg_base_addr);
+extern void dwc_otg_core_init(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_cil_remove(dwc_otg_core_if_t *_core_if);
+
+extern void dwc_otg_enable_global_interrupts(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_disable_global_interrupts(dwc_otg_core_if_t *_core_if);
+
+extern uint8_t dwc_otg_is_device_mode(dwc_otg_core_if_t *_core_if);
+extern uint8_t dwc_otg_is_host_mode(dwc_otg_core_if_t *_core_if);
+
+extern uint8_t dwc_otg_is_dma_enable(dwc_otg_core_if_t *core_if);
+
+/** This function should be called on every hardware interrupt. */
+extern int32_t dwc_otg_handle_common_intr(dwc_otg_core_if_t *_core_if);
+
+/* Register access functions */
+void dwc_write_reg32(volatile uint32_t *addr, uint32_t value);
+uint32_t dwc_read_reg32(volatile uint32_t *addr);
+
+/** @name OTG Core Parameters */
+/** @{ */
+
+/**
+ * Specifies the OTG capabilities. The driver will automatically
+ * detect the value for this parameter if none is specified.
+ * 0 - HNP and SRP capable (default)
+ * 1 - SRP Only capable
+ * 2 - No HNP/SRP capable
+ */
+extern int dwc_otg_set_param_otg_cap(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_otg_cap(dwc_otg_core_if_t *core_if);
+#define DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE 0
+#define DWC_OTG_CAP_PARAM_SRP_ONLY_CAPABLE 1
+#define DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE 2
+#define dwc_param_otg_cap_default DWC_OTG_CAP_PARAM_HNP_SRP_CAPABLE
+
+extern int dwc_otg_set_param_opt(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_opt(dwc_otg_core_if_t *core_if);
+#define dwc_param_opt_default 1
+
+/**
+ * Specifies whether to use slave or DMA mode for accessing the data
+ * FIFOs. The driver will automatically detect the value for this
+ * parameter if none is specified.
+ * 0 - Slave
+ * 1 - DMA (default, if available)
+ */
+extern int dwc_otg_set_param_dma_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_enable_default 1
+
+/**
+ * When DMA mode is enabled specifies whether to use
+ * address DMA or DMA Descritor mode for accessing the data
+ * FIFOs in device mode. The driver will automatically detect
+ * the value for this parameter if none is specified.
+ * 0 - address DMA
+ * 1 - DMA Descriptor(default, if available)
+ */
+extern int dwc_otg_set_param_dma_desc_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_desc_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_desc_enable_default 0 /* Broadcom BCM2708 */
+
+/** The DMA Burst size (applicable only for External DMA
+ * Mode). 1, 4, 8 16, 32, 64, 128, 256 (default 32)
+ */
+extern int dwc_otg_set_param_dma_burst_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dma_burst_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_dma_burst_size_default 32
+
+/**
+ * Specifies the maximum speed of operation in host and device mode.
+ * The actual speed depends on the speed of the attached device and
+ * the value of phy_type. The actual speed depends on the speed of the
+ * attached device.
+ * 0 - High Speed (default)
+ * 1 - Full Speed
+ */
+extern int dwc_otg_set_param_speed(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_speed(dwc_otg_core_if_t *core_if);
+#define dwc_param_speed_default 0
+#define DWC_SPEED_PARAM_HIGH 0
+#define DWC_SPEED_PARAM_FULL 1
+
+/** Specifies whether low power mode is supported when attached
+ * to a Full Speed or Low Speed device in host mode.
+ * 0 - Don't support low power mode (default)
+ * 1 - Support low power mode
+ */
+extern int dwc_otg_set_param_host_support_fs_ls_low_power(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_support_fs_ls_low_power(dwc_otg_core_if_t
+ *core_if);
+#define dwc_param_host_support_fs_ls_low_power_default 0
+
+/** Specifies the PHY clock rate in low power mode when connected to a
+ * Low Speed device in host mode. This parameter is applicable only if
+ * HOST_SUPPORT_FS_LS_LOW_POWER is enabled. If PHY_TYPE is set to FS
+ * then defaults to 6 MHZ otherwise 48 MHZ.
+ *
+ * 0 - 48 MHz
+ * 1 - 6 MHz
+ */
+extern int dwc_otg_set_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_ls_low_power_phy_clk(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_ls_low_power_phy_clk_default 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_48MHZ 0
+#define DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ 1
+
+/**
+ * 0 - Use cC FIFO size parameters
+ * 1 - Allow dynamic FIFO sizing (default)
+ */
+extern int dwc_otg_set_param_enable_dynamic_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_enable_dynamic_fifo(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_enable_dynamic_fifo_default 1
+
+/** Total number of 4-byte words in the data FIFO memory. This
+ * memory includes the Rx FIFO, non-periodic Tx FIFO, and periodic
+ * Tx FIFOs.
+ * 32 to 32768 (default 8192)
+ * Note: The total FIFO memory depth in the FPGA configuration is 8192.
+ */
+extern int dwc_otg_set_param_data_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_data_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_data_fifo_size_default 0xFF0 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the Rx FIFO in device mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1064)
+ */
+extern int dwc_otg_set_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dev_rx_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_dev_rx_fifo_size_default 1064
+
+/** Number of 4-byte words in the non-periodic Tx FIFO in device mode
+ * when dynamic FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_dev_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_dev_nperio_tx_fifo_size_default 1024
+
+/** Number of 4-byte words in each of the periodic Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+extern int dwc_otg_set_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val, int fifo_num);
+extern int32_t dwc_otg_get_param_dev_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int fifo_num);
+#define dwc_param_dev_perio_tx_fifo_size_default 256
+
+/** Number of 4-byte words in the Rx FIFO in host mode when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_host_rx_fifo_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_host_rx_fifo_size_default 774 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the non-periodic Tx FIFO in host mode
+ * when Dynamic FIFO sizing is enabled in the core.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_nperio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_nperio_tx_fifo_size_default 0x100 /* Broadcom BCM2708 */
+
+/** Number of 4-byte words in the host periodic Tx FIFO when dynamic
+ * FIFO sizing is enabled.
+ * 16 to 32768 (default 1024)
+ */
+extern int dwc_otg_set_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if, int32_t val);
+extern int32_t dwc_otg_get_param_host_perio_tx_fifo_size(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_host_perio_tx_fifo_size_default 0x200 /* Broadcom BCM2708 */
+
+/** The maximum transfer size supported in bytes.
+ * 2047 to 65535 (default 65535)
+ */
+extern int dwc_otg_set_param_max_transfer_size(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_max_transfer_size(dwc_otg_core_if_t *core_if);
+#define dwc_param_max_transfer_size_default 65535
+
+/** The maximum number of packets in a transfer.
+ * 15 to 511 (default 511)
+ */
+extern int dwc_otg_set_param_max_packet_count(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_max_packet_count(dwc_otg_core_if_t *core_if);
+#define dwc_param_max_packet_count_default 511
+
+/** The number of host channel registers to use.
+ * 1 to 16 (default 12)
+ * Note: The FPGA configuration supports a maximum of 12 host channels.
+ */
+extern int dwc_otg_set_param_host_channels(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_host_channels(dwc_otg_core_if_t *core_if);
+#define dwc_param_host_channels_default 12
+
+/** The number of endpoints in addition to EP0 available for device
+ * mode operations.
+ * 1 to 15 (default 6 IN and OUT)
+ * Note: The FPGA configuration supports a maximum of 6 IN and OUT
+ * endpoints in addition to EP0.
+ */
+extern int dwc_otg_set_param_dev_endpoints(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_dev_endpoints(dwc_otg_core_if_t *core_if);
+#define dwc_param_dev_endpoints_default 6
+
+/**
+ * Specifies the type of PHY interface to use. By default, the driver
+ * will automatically detect the phy_type.
+ *
+ * 0 - Full Speed PHY
+ * 1 - UTMI+ (default)
+ * 2 - ULPI
+ */
+extern int dwc_otg_set_param_phy_type(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_phy_type(dwc_otg_core_if_t *core_if);
+#define DWC_PHY_TYPE_PARAM_FS 0
+#define DWC_PHY_TYPE_PARAM_UTMI 1
+#define DWC_PHY_TYPE_PARAM_ULPI 2
+#define dwc_param_phy_type_default DWC_PHY_TYPE_PARAM_UTMI
+
+/**
+ * Specifies the UTMI+ Data Width. This parameter is
+ * applicable for a PHY_TYPE of UTMI+ or ULPI. (For a ULPI
+ * PHY_TYPE, this parameter indicates the data width between
+ * the MAC and the ULPI Wrapper.) Also, this parameter is
+ * applicable only if the OTG_HSPHY_WIDTH cC parameter was set
+ * to "8 and 16 bits", meaning that the core has been
+ * configured to work at either data path width.
+ *
+ * 8 or 16 bits (default 16)
+ */
+extern int dwc_otg_set_param_phy_utmi_width(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_utmi_width(dwc_otg_core_if_t *core_if);
+#define dwc_param_phy_utmi_width_default 8 /* Broadcom BCM2708 */
+
+/**
+ * Specifies whether the ULPI operates at double or single
+ * data rate. This parameter is only applicable if PHY_TYPE is
+ * ULPI.
+ *
+ * 0 - single data rate ULPI interface with 8 bit wide data
+ * bus (default)
+ * 1 - double data rate ULPI interface with 4 bit wide data
+ * bus
+ */
+extern int dwc_otg_set_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_ulpi_ddr(dwc_otg_core_if_t *core_if);
+#define dwc_param_phy_ulpi_ddr_default 0
+
+/**
+ * Specifies whether to use the internal or external supply to
+ * drive the vbus with a ULPI phy.
+ */
+extern int dwc_otg_set_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_phy_ulpi_ext_vbus(dwc_otg_core_if_t *core_if);
+#define DWC_PHY_ULPI_INTERNAL_VBUS 0
+#define DWC_PHY_ULPI_EXTERNAL_VBUS 1
+#define dwc_param_phy_ulpi_ext_vbus_default DWC_PHY_ULPI_INTERNAL_VBUS
+
+/**
+ * Specifies whether to use the I2Cinterface for full speed PHY. This
+ * parameter is only applicable if PHY_TYPE is FS.
+ * 0 - No (default)
+ * 1 - Yes
+ */
+extern int dwc_otg_set_param_i2c_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_i2c_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_i2c_enable_default 0
+
+extern int dwc_otg_set_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_ulpi_fs_ls(dwc_otg_core_if_t *core_if);
+#define dwc_param_ulpi_fs_ls_default 0
+
+extern int dwc_otg_set_param_ts_dline(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_ts_dline(dwc_otg_core_if_t *core_if);
+#define dwc_param_ts_dline_default 0
+
+/**
+ * Specifies whether dedicated transmit FIFOs are
+ * enabled for non periodic IN endpoints in device mode
+ * 0 - No
+ * 1 - Yes
+ */
+extern int dwc_otg_set_param_en_multiple_tx_fifo(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_en_multiple_tx_fifo(dwc_otg_core_if_t *
+ core_if);
+#define dwc_param_en_multiple_tx_fifo_default 1
+
+/** Number of 4-byte words in each of the Tx FIFOs in device
+ * mode when dynamic FIFO sizing is enabled.
+ * 4 to 768 (default 256)
+ */
+extern int dwc_otg_set_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num, int32_t val);
+extern int32_t dwc_otg_get_param_dev_tx_fifo_size(dwc_otg_core_if_t *core_if,
+ int fifo_num);
+#define dwc_param_dev_tx_fifo_size_default 256
+
+/** Thresholding enable flag-
+ * bit 0 - enable non-ISO Tx thresholding
+ * bit 1 - enable ISO Tx thresholding
+ * bit 2 - enable Rx thresholding
+ */
+extern int dwc_otg_set_param_thr_ctl(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_thr_ctl(dwc_otg_core_if_t *core_if, int fifo_num);
+#define dwc_param_thr_ctl_default 0
+
+/** Thresholding length for Tx
+ * FIFOs in 32 bit DWORDs
+ */
+extern int dwc_otg_set_param_tx_thr_length(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_tx_thr_length(dwc_otg_core_if_t *core_if);
+#define dwc_param_tx_thr_length_default 64
+
+/** Thresholding length for Rx
+ * FIFOs in 32 bit DWORDs
+ */
+extern int dwc_otg_set_param_rx_thr_length(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_rx_thr_length(dwc_otg_core_if_t *core_if);
+#define dwc_param_rx_thr_length_default 64
+
+/**
+ * Specifies whether LPM (Link Power Management) support is enabled
+ */
+extern int dwc_otg_set_param_lpm_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_lpm_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_lpm_enable_default 0
+
+/**
+ * Specifies whether PTI enhancement is enabled
+ */
+extern int dwc_otg_set_param_pti_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_pti_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_pti_enable_default 0
+
+/**
+ * Specifies whether MPI enhancement is enabled
+ */
+extern int dwc_otg_set_param_mpi_enable(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_mpi_enable(dwc_otg_core_if_t *core_if);
+#define dwc_param_mpi_enable_default 0
+
+/**
+ * Specifies whether IC_USB capability is enabled
+ */
+extern int dwc_otg_set_param_ic_usb_cap(dwc_otg_core_if_t *core_if,
+ int32_t val);
+extern int32_t dwc_otg_get_param_ic_usb_cap(dwc_otg_core_if_t *core_if);
+#define dwc_param_ic_usb_cap_default 0
+
+extern int dwc_otg_set_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if, int32_t val);
+extern int32_t dwc_otg_get_param_ahb_thr_ratio(dwc_otg_core_if_t *core_if);
+#define dwc_param_ahb_thr_ratio_default 0
+
+/** @} */
+
+/** @name Access to registers and bit-fields */
+
+/**
+ * Dump core registers and SPRAM
+ */
+extern void dwc_otg_dump_dev_registers(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_spram(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_host_registers(dwc_otg_core_if_t *_core_if);
+extern void dwc_otg_dump_global_registers(dwc_otg_core_if_t *_core_if);
+
+/**
+ * Get host negotiation status.
+ */
+extern uint32_t dwc_otg_get_hnpstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get srp status
+ */
+extern uint32_t dwc_otg_get_srpstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Set hnpreq bit in the GOTGCTL register.
+ */
+extern void dwc_otg_set_hnpreq(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get Content of SNPSID register.
+ */
+extern uint32_t dwc_otg_get_gsnpsid(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get current mode.
+ * Returns 0 if in device mode, and 1 if in host mode.
+ */
+extern uint32_t dwc_otg_get_mode(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of hnpcapable field in the GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_hnpcapable(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of hnpcapable field in the GUSBCFG register
+ */
+extern void dwc_otg_set_hnpcapable(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of srpcapable field in the GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_srpcapable(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of srpcapable field in the GUSBCFG register
+ */
+extern void dwc_otg_set_srpcapable(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of devspeed field in the DCFG register
+ */
+extern uint32_t dwc_otg_get_devspeed(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of devspeed field in the DCFG register
+ */
+extern void dwc_otg_set_devspeed(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get the value of busconnected field from the HPRT0 register
+ */
+extern uint32_t dwc_otg_get_busconnected(dwc_otg_core_if_t *core_if);
+
+/**
+ * Gets the device enumeration Speed.
+ */
+extern uint32_t dwc_otg_get_enumspeed(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of prtpwr field from the HPRT0 register
+ */
+extern uint32_t dwc_otg_get_prtpower(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of prtpwr field from the HPRT0 register
+ */
+extern void dwc_otg_set_prtpower(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of prtsusp field from the HPRT0 regsiter
+ */
+extern uint32_t dwc_otg_get_prtsuspend(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of prtpwr field from the HPRT0 register
+ */
+extern void dwc_otg_set_prtsuspend(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Set value of prtres field from the HPRT0 register
+ *FIXME Remove?
+ */
+extern void dwc_otg_set_prtresume(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of rmtwkupsig bit in DCTL register
+ */
+extern uint32_t dwc_otg_get_remotewakesig(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of prt_sleep_sts field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpm_portsleepstatus(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of rem_wkup_en field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpm_remotewakeenabled(dwc_otg_core_if_t *core_if);
+
+/**
+ * Get value of appl_resp field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_lpmresponse(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of appl_resp field from the GLPMCFG register
+ */
+extern void dwc_otg_set_lpmresponse(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of hsic_connect field from the GLPMCFG register
+ */
+extern uint32_t dwc_otg_get_hsic_connect(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of hsic_connect field from the GLPMCFG register
+ */
+extern void dwc_otg_set_hsic_connect(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * Get value of inv_sel_hsic field from the GLPMCFG register.
+ */
+extern uint32_t dwc_otg_get_inv_sel_hsic(dwc_otg_core_if_t *core_if);
+/**
+ * Set value of inv_sel_hsic field from the GLPMFG register.
+ */
+extern void dwc_otg_set_inv_sel_hsic(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/*
+ * Some functions for accessing registers
+ */
+
+/**
+ * GOTGCTL register
+ */
+extern uint32_t dwc_otg_get_gotgctl(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gotgctl(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GUSBCFG register
+ */
+extern uint32_t dwc_otg_get_gusbcfg(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gusbcfg(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GRXFSIZ register
+ */
+extern uint32_t dwc_otg_get_grxfsiz(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_grxfsiz(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GNPTXFSIZ register
+ */
+extern uint32_t dwc_otg_get_gnptxfsiz(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gnptxfsiz(dwc_otg_core_if_t *core_if, uint32_t val);
+
+extern uint32_t dwc_otg_get_gpvndctl(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_gpvndctl(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GGPIO register
+ */
+extern uint32_t dwc_otg_get_ggpio(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_ggpio(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * GUID register
+ */
+extern uint32_t dwc_otg_get_guid(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_guid(dwc_otg_core_if_t *core_if, uint32_t val);
+
+/**
+ * HPRT0 register
+ */
+extern uint32_t dwc_otg_get_hprt0(dwc_otg_core_if_t *core_if);
+extern void dwc_otg_set_hprt0(dwc_otg_core_if_t *core_if, uint32_t val);
+extern uint32_t dwc_otg_read_hprt0(dwc_otg_core_if_t *_core_if);
+
+/**
+ * GHPTXFSIZE
+ */
+extern uint32_t dwc_otg_get_hptxfsiz(dwc_otg_core_if_t *core_if);
+
+/**
+ * Init channel @hc_num with provided parameters
+ */
+extern void dwc_otg_hc_init(dwc_otg_core_if_t *core_if, uint8_t hc_num,
+ uint8_t dev_addr, uint8_t ep_num, uint8_t ep_is_in,
+ uint8_t ep_type, uint16_t max_packet);
+
+
+/**
+ * Host controller initialization part
+ */
+extern void dwc_otg_core_host_init(dwc_otg_core_if_t *core_if);
+
+/** @} */
+
+#endif /* __DWC_CORE_IF_H__ */
diff --git a/drivers/usb/host/dwc2_otg_regs.h b/drivers/usb/host/dwc2_otg_regs.h
new file mode 100644
index 0000000..765e46e
--- /dev/null
+++ b/drivers/usb/host/dwc2_otg_regs.h
@@ -0,0 +1,1625 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_regs.h $
+ * $Revision: #76 $
+ * $Date: 2009/04/02 $
+ * $Change: 1224216 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ * ========================================================================== */
+
+#ifndef __DWC_OTG_REGS_H__
+#define __DWC_OTG_REGS_H__
+
+#include "dwc2_otg.h"
+
+/**
+ * @file
+ *
+ * This file contains the data structures for accessing the DWC_otg core registers.
+ *
+ * The application interfaces with the HS OTG core by reading from and
+ * writing to the Control and Status Register (CSR) space through the
+ * AHB Slave interface. These registers are 32 bits wide, and the
+ * addresses are 32-bit-block aligned.
+ * CSRs are classified as follows:
+ * - Core Global Registers
+ * - Device Mode Registers
+ * - Device Global Registers
+ * - Device Endpoint Specific Registers
+ * - Host Mode Registers
+ * - Host Global Registers
+ * - Host Port CSRs
+ * - Host Channel Specific Registers
+ *
+ * Only the Core Global registers can be accessed in both Device and
+ * Host modes. When the HS OTG core is operating in one mode, either
+ * Device or Host, the application must not access registers from the
+ * other mode. When the core switches from one mode to another, the
+ * registers in the new mode of operation must be reprogrammed as they
+ * would be after a power-on reset.
+ */
+
+/****************************************************************************/
+/** DWC_otg Core registers .
+ * The dwc_otg_core_global_regs structure defines the size
+ * and relative field offsets for the Core Global registers.
+ */
+typedef struct dwc_otg_core_global_regs {
+ /** OTG Control and Status Register. <i>Offset: 000h</i> */
+ volatile uint32_t gotgctl;
+ /** OTG Interrupt Register. <i>Offset: 004h</i> */
+ volatile uint32_t gotgint;
+ /**Core AHB Configuration Register. <i>Offset: 008h</i> */
+ volatile uint32_t gahbcfg;
+
+#define DWC_GLBINTRMASK 0x0001
+#define DWC_DMAENABLE 0x0020
+#define DWC_NPTXEMPTYLVL_EMPTY 0x0080
+#define DWC_NPTXEMPTYLVL_HALFEMPTY 0x0000
+#define DWC_PTXEMPTYLVL_EMPTY 0x0100
+#define DWC_PTXEMPTYLVL_HALFEMPTY 0x0000
+
+ /**Core USB Configuration Register. <i>Offset: 00Ch</i> */
+ volatile uint32_t gusbcfg;
+ /**Core Reset Register. <i>Offset: 010h</i> */
+ volatile uint32_t grstctl;
+ /**Core Interrupt Register. <i>Offset: 014h</i> */
+ volatile uint32_t gintsts;
+ /**Core Interrupt Mask Register. <i>Offset: 018h</i> */
+ volatile uint32_t gintmsk;
+ /**Receive Status Queue Read Register (Read Only). <i>Offset: 01Ch</i> */
+ volatile uint32_t grxstsr;
+ /**Receive Status Queue Read & POP Register (Read Only). <i>Offset: 020h</i>*/
+ volatile uint32_t grxstsp;
+ /**Receive FIFO Size Register. <i>Offset: 024h</i> */
+ volatile uint32_t grxfsiz;
+ /**Non Periodic Transmit FIFO Size Register. <i>Offset: 028h</i> */
+ volatile uint32_t gnptxfsiz;
+ /**Non Periodic Transmit FIFO/Queue Status Register (Read
+ * Only). <i>Offset: 02Ch</i> */
+ volatile uint32_t gnptxsts;
+ /**I2C Access Register. <i>Offset: 030h</i> */
+ volatile uint32_t gi2cctl;
+ /**PHY Vendor Control Register. <i>Offset: 034h</i> */
+ volatile uint32_t gpvndctl;
+ /**General Purpose Input/Output Register. <i>Offset: 038h</i> */
+ volatile uint32_t ggpio;
+ /**User ID Register. <i>Offset: 03Ch</i> */
+ volatile uint32_t guid;
+ /**Synopsys ID Register (Read Only). <i>Offset: 040h</i> */
+ volatile uint32_t gsnpsid;
+ /**User HW Config1 Register (Read Only). <i>Offset: 044h</i> */
+ volatile uint32_t ghwcfg1;
+ /**User HW Config2 Register (Read Only). <i>Offset: 048h</i> */
+ volatile uint32_t ghwcfg2;
+#define DWC_SLAVE_ONLY_ARCH 0
+#define DWC_EXT_DMA_ARCH 1
+#define DWC_INT_DMA_ARCH 2
+
+#define DWC_MODE_HNP_SRP_CAPABLE 0
+#define DWC_MODE_SRP_ONLY_CAPABLE 1
+#define DWC_MODE_NO_HNP_SRP_CAPABLE 2
+#define DWC_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_MODE_SRP_CAPABLE_HOST 5
+#define DWC_MODE_NO_SRP_CAPABLE_HOST 6
+
+ /**User HW Config3 Register (Read Only). <i>Offset: 04Ch</i> */
+ volatile uint32_t ghwcfg3;
+ /**User HW Config4 Register (Read Only). <i>Offset: 050h</i>*/
+ volatile uint32_t ghwcfg4;
+ /** Core LPM Configuration register */
+ volatile uint32_t glpmcfg;
+ /** Reserved <i>Offset: 058h-0FFh</i> */
+ volatile uint32_t reserved[42];
+ /** Host Periodic Transmit FIFO Size Register. <i>Offset: 100h</i> */
+ volatile uint32_t hptxfsiz;
+ /** Device Periodic Transmit FIFO#n Register if dedicated fifos are disabled,
+ otherwise Device Transmit FIFO#n Register.
+ * <i>Offset: 104h + (FIFO_Number-1)*04h, 1 <= FIFO Number <= 15 (1<=n<=15).</i> */
+ volatile uint32_t dptxfsiz_dieptxf[15];
+} dwc_otg_core_global_regs_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Control
+ * and Status Register (GOTGCTL). Set the bits using the bit
+ * fields then write the <i>d32</i> value to the register.
+ */
+typedef union gotgctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned sesreqscs:1;
+ unsigned sesreq:1;
+ unsigned reserved2_7:6;
+ unsigned hstnegscs:1;
+ unsigned hnpreq:1;
+ unsigned hstsethnpen:1;
+ unsigned devhnpen:1;
+ unsigned reserved12_15:4;
+ unsigned conidsts:1;
+ unsigned reserved17:1;
+ unsigned asesvld:1;
+ unsigned bsesvld:1;
+ unsigned currmod:1;
+ unsigned reserved21_31:11;
+ } b;
+} gotgctl_data_t;
+
+/**
+ * This union represents the bit fields of the Core OTG Interrupt Register
+ * (GOTGINT). Set/clear the bits using the bit fields then write the <i>d32</i>
+ * value to the register.
+ */
+typedef union gotgint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Current Mode */
+ unsigned reserved0_1:2;
+
+ /** Session End Detected */
+ unsigned sesenddet:1;
+
+ unsigned reserved3_7:5;
+
+ /** Session Request Success Status Change */
+ unsigned sesreqsucstschng:1;
+ /** Host Negotiation Success Status Change */
+ unsigned hstnegsucstschng:1;
+
+ unsigned reserver10_16:7;
+
+ /** Host Negotiation Detected */
+ unsigned hstnegdet:1;
+ /** A-Device Timeout Change */
+ unsigned adevtoutchng:1;
+ /** Debounce Done */
+ unsigned debdone:1;
+
+ unsigned reserved31_20:12;
+
+ } b;
+} gotgint_data_t;
+
+/**
+ * This union represents the bit fields of the Core AHB Configuration
+ * Register (GAHBCFG). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gahbcfg_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned glblintrmsk:1;
+#define DWC_GAHBCFG_GLBINT_ENABLE 1
+
+ unsigned hburstlen:4;
+#define DWC_GAHBCFG_INT_DMA_BURST_SINGLE 0
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR 1
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR4 3
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR8 5
+#define DWC_GAHBCFG_INT_DMA_BURST_INCR16 7
+
+ unsigned dmaenable:1;
+#define DWC_GAHBCFG_DMAENABLE 1
+ unsigned reserved:1;
+ unsigned nptxfemplvl_txfemplvl:1;
+ unsigned ptxfemplvl:1;
+#define DWC_GAHBCFG_TXFEMPTYLVL_EMPTY 1
+#define DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY 0
+ unsigned reserved9_31:23;
+ } b;
+} gahbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core USB Configuration
+ * Register (GUSBCFG). Set the bits using the bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union gusbcfg_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned toutcal:3;
+ unsigned phyif:1;
+ unsigned ulpi_utmi_sel:1;
+ unsigned fsintf:1;
+ unsigned physel:1;
+ unsigned ddrsel:1;
+ unsigned srpcap:1;
+ unsigned hnpcap:1;
+ unsigned usbtrdtim:4;
+ unsigned nptxfrwnden:1;
+ unsigned phylpwrclksel:1;
+ unsigned otgutmifssel:1;
+ unsigned ulpi_fsls:1;
+ unsigned ulpi_auto_res:1;
+ unsigned ulpi_clk_sus_m:1;
+ unsigned ulpi_ext_vbus_drv:1;
+ unsigned ulpi_int_vbus_indicator:1;
+ unsigned term_sel_dl_pulse:1;
+ unsigned reserved23_25:3;
+ unsigned ic_usb_cap:1;
+ unsigned ic_traffic_pull_remove:1;
+ unsigned tx_end_delay:1;
+ unsigned reserved29_31:3;
+ } b;
+} gusbcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core LPM Configuration
+ * Register (GLPMCFG). Set the bits using bit fields then write
+ * the <i>d32</i> value to the register.
+ */
+typedef union glpmctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** LPM-Capable (LPMCap) (Device and Host)
+ * The application uses this bit to control
+ * the DWC_otg core LPM capabilities.
+ */
+ unsigned lpm_cap_en:1;
+ /** LPM response programmed by application (AppL1Res) (Device)
+ * Handshake response to LPM token pre-programmed
+ * by device application software.
+ */
+ unsigned appl_resp:1;
+ /** Host Initiated Resume Duration (HIRD) (Device and Host)
+ * In Host mode this field indicates the value of HIRD
+ * to be sent in an LPM transaction.
+ * In Device mode this field is updated with the
+ * Received LPM Token HIRD bmAttribute
+ * when an ACK/NYET/STALL response is sent
+ * to an LPM transaction.
+ */
+ unsigned hird:4;
+ /** RemoteWakeEnable (bRemoteWake) (Device and Host)
+ * In Host mode this bit indicates the value of remote
+ * wake up to be sent in wIndex field of LPM transaction.
+ * In Device mode this field is updated with the
+ * Received LPM Token bRemoteWake bmAttribute
+ * when an ACK/NYET/STALL response is sent
+ * to an LPM transaction.
+ */
+ unsigned rem_wkup_en:1;
+ /** Enable utmi_sleep_n (EnblSlpM) (Device and Host)
+ * The application uses this bit to control
+ * the utmi_sleep_n assertion to the PHY when in L1 state.
+ */
+ unsigned en_utmi_sleep:1;
+ /** HIRD Threshold (HIRD_Thres) (Device and Host)
+ */
+ unsigned hird_thres:5;
+ /** LPM Response (CoreL1Res) (Device and Host)
+ * In Host mode this bit contains handsake response to
+ * LPM transaction.
+ * In Device mode the response of the core to
+ * LPM transaction received is reflected in these two bits.
+ * - 0x0: ERROR (No handshake response)
+ * - 0x1: STALL
+ * - 0x2: NYET
+ * - 0x3: ACK
+ */
+ unsigned lpm_resp:2;
+ /** Port Sleep Status (SlpSts) (Device and Host)
+ * This bit is set as long as a Sleep condition
+ * is present on the USB bus.
+ */
+ unsigned prt_sleep_sts:1;
+ /** Sleep State Resume OK (L1ResumeOK) (Device and Host)
+ * Indicates that the application or host
+ * can start resume from Sleep state.
+ */
+ unsigned sleep_state_resumeok:1;
+ /** LPM channel Index (LPM_Chnl_Indx) (Host)
+ * The channel number on which the LPM transaction
+ * has to be applied while sending
+ * an LPM transaction to the local device.
+ */
+ unsigned lpm_chan_index:4;
+ /** LPM Retry Count (LPM_Retry_Cnt) (Host)
+ * Number host retries that would be performed
+ * if the device response was not valid response.
+ */
+ unsigned retry_count:3;
+ /** Send LPM Transaction (SndLPM) (Host)
+ * When set by application software,
+ * an LPM transaction containing two tokens
+ * is sent.
+ */
+ unsigned send_lpm:1;
+ /** LPM Retry status (LPM_RetryCnt_Sts) (Host)
+ * Number of LPM Host Retries still remaining
+ * to be transmitted for the current LPM sequence
+ */
+ unsigned retry_count_sts:3;
+ unsigned reserved28_29:2;
+ /** In host mode once this bit is set, the host
+ * configures to drive the HSIC Idle state on the bus.
+ * It then waits for the device to initiate the Connect sequence.
+ * In device mode once this bit is set, the device waits for
+ * the HSIC Idle line state on the bus. Upon receving the Idle
+ * line state, it initiates the HSIC Connect sequence.
+ */
+ unsigned hsic_connect:1;
+ /** This bit overrides and functionally inverts
+ * the if_select_hsic input port signal.
+ */
+ unsigned inv_sel_hsic:1;
+ } b;
+} glpmcfg_data_t;
+
+/**
+ * This union represents the bit fields of the Core Reset Register
+ * (GRSTCTL). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union grstctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Core Soft Reset (CSftRst) (Device and Host)
+ *
+ * The application can flush the control logic in the
+ * entire core using this bit. This bit resets the
+ * pipelines in the AHB Clock domain as well as the
+ * PHY Clock domain.
+ *
+ * The state machines are reset to an IDLE state, the
+ * control bits in the CSRs are cleared, all the
+ * transmit FIFOs and the receive FIFO are flushed.
+ *
+ * The status mask bits that control the generation of
+ * the interrupt, are cleared, to clear the
+ * interrupt. The interrupt status bits are not
+ * cleared, so the application can get the status of
+ * any events that occurred in the core after it has
+ * set this bit.
+ *
+ * Any transactions on the AHB are terminated as soon
+ * as possible following the protocol. Any
+ * transactions on the USB are terminated immediately.
+ *
+ * The configuration settings in the CSRs are
+ * unchanged, so the software doesn't have to
+ * reprogram these registers (Device
+ * Configuration/Host Configuration/Core System
+ * Configuration/Core PHY Configuration).
+ *
+ * The application can write to this bit, any time it
+ * wants to reset the core. This is a self clearing
+ * bit and the core clears this bit after all the
+ * necessary logic is reset in the core, which may
+ * take several clocks, depending on the current state
+ * of the core.
+ */
+ unsigned csftrst:1;
+ /** Hclk Soft Reset
+ *
+ * The application uses this bit to reset the control logic in
+ * the AHB clock domain. Only AHB clock domain pipelines are
+ * reset.
+ */
+ unsigned hsftrst:1;
+ /** Host Frame Counter Reset (Host Only)<br>
+ *
+ * The application can reset the (micro)frame number
+ * counter inside the core, using this bit. When the
+ * (micro)frame counter is reset, the subsequent SOF
+ * sent out by the core, will have a (micro)frame
+ * number of 0.
+ */
+ unsigned hstfrm:1;
+ /** In Token Sequence Learning Queue Flush
+ * (INTknQFlsh) (Device Only)
+ */
+ unsigned intknqflsh:1;
+ /** RxFIFO Flush (RxFFlsh) (Device and Host)
+ *
+ * The application can flush the entire Receive FIFO
+ * using this bit. <p>The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is reading from the RxFIFO nor the MAC
+ * is writing the data in to the FIFO. <p>The
+ * application should wait until the bit is cleared
+ * before performing any other operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned rxfflsh:1;
+ /** TxFIFO Flush (TxFFlsh) (Device and Host).
+ *
+ * This bit is used to selectively flush a single or
+ * all transmit FIFOs. The application must first
+ * ensure that the core is not in the middle of a
+ * transaction. <p>The application should write into
+ * this bit, only after making sure that neither the
+ * DMA engine is writing into the TxFIFO nor the MAC
+ * is reading the data out of the FIFO. <p>The
+ * application should wait until the core clears this
+ * bit, before performing any operations. This bit
+ * will takes 8 clocks (slowest of PHY or AHB clock)
+ * to clear.
+ */
+ unsigned txfflsh:1;
+
+ /** TxFIFO Number (TxFNum) (Device and Host).
+ *
+ * This is the FIFO number which needs to be flushed,
+ * using the TxFIFO Flush bit. This field should not
+ * be changed until the TxFIFO Flush bit is cleared by
+ * the core.
+ * - 0x0: Non Periodic TxFIFO Flush
+ * - 0x1: Periodic TxFIFO #1 Flush in device mode
+ * or Periodic TxFIFO in host mode
+ * - 0x2: Periodic TxFIFO #2 Flush in device mode.
+ * - ...
+ * - 0xF: Periodic TxFIFO #15 Flush in device mode
+ * - 0x10: Flush all the Transmit NonPeriodic and
+ * Transmit Periodic FIFOs in the core
+ */
+ unsigned txfnum:5;
+ /** Reserved */
+ unsigned reserved11_29:19;
+ /** DMA Request Signal. Indicated DMA request is in
+ * probress. Used for debug purpose. */
+ unsigned dmareq:1;
+ /** AHB Master Idle. Indicates the AHB Master State
+ * Machine is in IDLE condition. */
+ unsigned ahbidle:1;
+ } b;
+} grstctl_t;
+
+/**
+ * This union represents the bit fields of the Core Interrupt Mask
+ * Register (GINTMSK). Set/clear the bits using the bit fields then
+ * write the <i>d32</i> value to the register.
+ */
+typedef union gintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned reserved0:1;
+ unsigned modemismatch:1;
+ unsigned otgintr:1;
+ unsigned sofintr:1;
+ unsigned rxstsqlvl:1;
+ unsigned nptxfempty:1;
+ unsigned ginnakeff:1;
+ unsigned goutnakeff:1;
+ unsigned reserved8:1;
+ unsigned i2cintr:1;
+ unsigned erlysuspend:1;
+ unsigned usbsuspend:1;
+ unsigned usbreset:1;
+ unsigned enumdone:1;
+ unsigned isooutdrop:1;
+ unsigned eopframe:1;
+ unsigned reserved16:1;
+ unsigned epmismatch:1;
+ unsigned inepintr:1;
+ unsigned outepintr:1;
+ unsigned incomplisoin:1;
+ unsigned incomplisoout:1;
+ unsigned reserved22_23:2;
+ unsigned portintr:1;
+ unsigned hcintr:1;
+ unsigned ptxfempty:1;
+ unsigned lpmtranrcvd:1;
+ unsigned conidstschng:1;
+ unsigned disconnect:1;
+ unsigned sessreqintr:1;
+ unsigned wkupintr:1;
+ } b;
+} gintmsk_data_t;
+/**
+ * This union represents the bit fields of the Core Interrupt Register
+ * (GINTSTS). Set/clear the bits using the bit fields then write the
+ * <i>d32</i> value to the register.
+ */
+typedef union gintsts_data {
+ /** raw register data */
+ uint32_t d32;
+#define DWC_SOF_INTR_MASK 0x0008
+ /** register bits */
+ struct {
+#define DWC_HOST_MODE 1
+ unsigned curmode:1;
+ unsigned modemismatch:1;
+ unsigned otgintr:1;
+ unsigned sofintr:1;
+ unsigned rxstsqlvl:1;
+ unsigned nptxfempty:1;
+ unsigned ginnakeff:1;
+ unsigned goutnakeff:1;
+ unsigned reserved8:1;
+ unsigned i2cintr:1;
+ unsigned erlysuspend:1;
+ unsigned usbsuspend:1;
+ unsigned usbreset:1;
+ unsigned enumdone:1;
+ unsigned isooutdrop:1;
+ unsigned eopframe:1;
+ unsigned intokenrx:1;
+ unsigned epmismatch:1;
+ unsigned inepint:1;
+ unsigned outepintr:1;
+ unsigned incomplisoin:1;
+ unsigned incomplisoout:1;
+ unsigned reserved22_23:2;
+ unsigned portintr:1;
+ unsigned hcintr:1;
+ unsigned ptxfempty:1;
+ unsigned lpmtranrcvd:1;
+ unsigned conidstschng:1;
+ unsigned disconnect:1;
+ unsigned sessreqintr:1;
+ unsigned wkupintr:1;
+ } b;
+} gintsts_data_t;
+
+/**
+ * This union represents the bit fields in the Device Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union device_grxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned epnum:4;
+ unsigned bcnt:11;
+ unsigned dpid:2;
+
+#define DWC_STS_DATA_UPDT 0x2 /* OUT Data Packet */
+#define DWC_STS_XFER_COMP 0x3 /* OUT Data Transfer Complete */
+
+#define DWC_DSTS_GOUT_NAK 0x1 /* Global OUT NAK */
+#define DWC_DSTS_SETUP_COMP 0x4 /* Setup Phase Complete */
+#define DWC_DSTS_SETUP_UPDT 0x6 /* SETUP Packet */
+ unsigned pktsts:4;
+ unsigned fn:4;
+ unsigned reserved:7;
+ } b;
+} device_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Receive Status Read and
+ * Pop Registers (GRXSTSR, GRXSTSP) Read the register into the <i>d32</i>
+ * element then read out the bits using the <i>b</i>it elements.
+ */
+typedef union host_grxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned chnum:4;
+ unsigned bcnt:11;
+ unsigned dpid:2;
+
+ unsigned pktsts:4;
+#define DWC_GRXSTS_PKTSTS_IN 0x2
+#define DWC_GRXSTS_PKTSTS_IN_XFER_COMP 0x3
+#define DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR 0x5
+#define DWC_GRXSTS_PKTSTS_CH_HALTED 0x7
+
+ unsigned reserved:11;
+ } b;
+} host_grxsts_data_t;
+
+/**
+ * This union represents the bit fields in the FIFO Size Registers (HPTXFSIZ,
+ * GNPTXFSIZ, DPTXFSIZn, DIEPTXFn). Read the register into the <i>d32</i> element then
+ * read out the bits using the <i>b</i>it elements.
+ */
+typedef union fifosize_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned startaddr:16;
+ unsigned depth:16;
+ } b;
+} fifosize_data_t;
+
+/**
+ * This union represents the bit fields in the Non-Periodic Transmit
+ * FIFO/Queue Status Register (GNPTXSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union gnptxsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned nptxfspcavail:16;
+ unsigned nptxqspcavail:8;
+ /** Top of the Non-Periodic Transmit Request Queue
+ * - bit 24 - Terminate (Last entry for the selected
+ * channel/EP)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - IN/OUT
+ * - 2'b01 - Zero Length OUT
+ * - 2'b10 - PING/Complete Split
+ * - 2'b11 - Channel Halt
+ * - bits 30:27 - Channel/EP Number
+ */
+ unsigned nptxqtop_terminate:1;
+ unsigned nptxqtop_token:2;
+ unsigned nptxqtop_chnep:4;
+ unsigned reserved:1;
+ } b;
+} gnptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Transmit
+ * FIFO Status Register (DTXFSTS). Read the register into the
+ * <i>d32</i> element then read out the bits using the <i>b</i>it
+ * elements.
+ */
+typedef union dtxfsts_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned txfspcavail:16;
+ unsigned reserved:16;
+ } b;
+} dtxfsts_data_t;
+
+/**
+ * This union represents the bit fields in the I2C Control Register
+ * (I2CCTL). Read the register into the <i>d32</i> element then read out the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union gi2cctl_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned rwdata:8;
+ unsigned regaddr:8;
+ unsigned addr:7;
+ unsigned i2cen:1;
+ unsigned ack:1;
+ unsigned i2csuspctl:1;
+ unsigned i2cdevaddr:2;
+ unsigned reserved:2;
+ unsigned rw:1;
+ unsigned bsydne:1;
+ } b;
+} gi2cctl_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config1
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg1_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ep_dir0:2;
+ unsigned ep_dir1:2;
+ unsigned ep_dir2:2;
+ unsigned ep_dir3:2;
+ unsigned ep_dir4:2;
+ unsigned ep_dir5:2;
+ unsigned ep_dir6:2;
+ unsigned ep_dir7:2;
+ unsigned ep_dir8:2;
+ unsigned ep_dir9:2;
+ unsigned ep_dir10:2;
+ unsigned ep_dir11:2;
+ unsigned ep_dir12:2;
+ unsigned ep_dir13:2;
+ unsigned ep_dir14:2;
+ unsigned ep_dir15:2;
+ } b;
+} hwcfg1_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config2
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg2_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /* GHWCFG2 */
+ unsigned op_mode:3;
+#define DWC_HWCFG2_OP_MODE_HNP_SRP_CAPABLE_OTG 0
+#define DWC_HWCFG2_OP_MODE_SRP_ONLY_CAPABLE_OTG 1
+#define DWC_HWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE_OTG 2
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_DEVICE 3
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE 4
+#define DWC_HWCFG2_OP_MODE_SRP_CAPABLE_HOST 5
+#define DWC_HWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST 6
+
+ unsigned architecture:2;
+ unsigned point2point:1;
+ unsigned hs_phy_type:2;
+#define DWC_HWCFG2_HS_PHY_TYPE_NOT_SUPPORTED 0
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI 1
+#define DWC_HWCFG2_HS_PHY_TYPE_ULPI 2
+#define DWC_HWCFG2_HS_PHY_TYPE_UTMI_ULPI 3
+
+ unsigned fs_phy_type:2;
+ unsigned num_dev_ep:4;
+ unsigned num_host_chan:4;
+ unsigned perio_ep_supported:1;
+ unsigned dynamic_fifo:1;
+ unsigned multi_proc_int:1;
+ unsigned reserved21:1;
+ unsigned nonperio_tx_q_depth:2;
+ unsigned host_perio_tx_q_depth:2;
+ unsigned dev_token_q_depth:5;
+ unsigned reserved31:1;
+ } b;
+} hwcfg2_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config3
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg3_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /* GHWCFG3 */
+ unsigned xfer_size_cntr_width:4;
+ unsigned packet_size_cntr_width:3;
+ unsigned otg_func:1;
+ unsigned i2c:1;
+ unsigned vendor_ctrl_if:1;
+ unsigned optional_features:1;
+ unsigned synch_reset_type:1;
+ unsigned otg_enable_ic_usb:1;
+ unsigned otg_enable_hsic:1;
+ unsigned reserved14:1;
+ unsigned otg_lpm_en:1;
+ unsigned dfifo_depth:16;
+ } b;
+} hwcfg3_data_t;
+
+/**
+ * This union represents the bit fields in the User HW Config4
+ * Register. Read the register into the <i>d32</i> element then read
+ * out the bits using the <i>b</i>it elements.
+ */
+typedef union hwcfg4_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned num_dev_perio_in_ep:4;
+ unsigned power_optimiz:1;
+ unsigned min_ahb_freq:9;
+ unsigned utmi_phy_data_width:2;
+ unsigned num_dev_mode_ctrl_ep:4;
+ unsigned iddig_filt_en:1;
+ unsigned vbus_valid_filt_en:1;
+ unsigned a_valid_filt_en:1;
+ unsigned b_valid_filt_en:1;
+ unsigned session_end_filt_en:1;
+ unsigned ded_fifo_en:1;
+ unsigned num_in_eps:4;
+ unsigned desc_dma:1;
+ unsigned desc_dma_dyn:1;
+ } b;
+} hwcfg4_data_t;
+
+/* Device Registers */
+
+/**
+ * Device Global Registers. <i>Offsets 800h-BFFh</i>
+ *
+ * The following structures define the size and relative field offsets
+ * for the Device Mode Registers.
+ *
+ * <i>These registers are visible only in Device mode and must not be
+ * accessed in Host mode, as the results are unknown.</i>
+ */
+typedef struct dwc_otg_dev_global_regs {
+ /** Device Configuration Register. <i>Offset 800h</i> */
+ volatile uint32_t dcfg;
+ /** Device Control Register. <i>Offset: 804h</i> */
+ volatile uint32_t dctl;
+ /** Device Status Register (Read Only). <i>Offset: 808h</i> */
+ volatile uint32_t dsts;
+ /** Reserved. <i>Offset: 80Ch</i> */
+ uint32_t unused;
+ /** Device IN Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 810h</i> */
+ volatile uint32_t diepmsk;
+ /** Device OUT Endpoint Common Interrupt Mask
+ * Register. <i>Offset: 814h</i> */
+ volatile uint32_t doepmsk;
+ /** Device All Endpoints Interrupt Register. <i>Offset: 818h</i> */
+ volatile uint32_t daint;
+ /** Device All Endpoints Interrupt Mask Register. <i>Offset:
+ * 81Ch</i> */
+ volatile uint32_t daintmsk;
+ /** Device IN Token Queue Read Register-1 (Read Only).
+ * <i>Offset: 820h</i> */
+ volatile uint32_t dtknqr1;
+ /** Device IN Token Queue Read Register-2 (Read Only).
+ * <i>Offset: 824h</i> */
+ volatile uint32_t dtknqr2;
+ /** Device VBUS discharge Register. <i>Offset: 828h</i> */
+ volatile uint32_t dvbusdis;
+ /** Device VBUS Pulse Register. <i>Offset: 82Ch</i> */
+ volatile uint32_t dvbuspulse;
+ /** Device IN Token Queue Read Register-3 (Read Only). /
+ * Device Thresholding control register (Read/Write)
+ * <i>Offset: 830h</i> */
+ volatile uint32_t dtknqr3_dthrctl;
+ /** Device IN Token Queue Read Register-4 (Read Only). /
+ * Device IN EPs empty Inr. Mask Register (Read/Write)
+ * <i>Offset: 834h</i> */
+ volatile uint32_t dtknqr4_fifoemptymsk;
+ /** Device Each Endpoint Interrupt Register (Read Only). /
+ * <i>Offset: 838h</i> */
+ volatile uint32_t deachint;
+ /** Device Each Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 83Ch</i> */
+ volatile uint32_t deachintmsk;
+ /** Device Each In Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 840h</i> */
+ volatile uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
+ /** Device Each Out Endpoint Interrupt mask Register (Read/Write). /
+ * <i>Offset: 880h</i> */
+ volatile uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
+} dwc_otg_device_global_regs_t;
+
+/* DMA Descriptor Specific Structures */
+
+/** Buffer status definitions */
+
+#define BS_HOST_READY 0x0
+#define BS_DMA_BUSY 0x1
+#define BS_DMA_DONE 0x2
+#define BS_HOST_BUSY 0x3
+
+/** Receive/Transmit status definitions */
+
+#define RTS_SUCCESS 0x0
+#define RTS_BUFFLUSH 0x1
+#define RTS_RESERVED 0x2
+#define RTS_BUFERR 0x3
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it, <i>b_iso_out</i> and
+ * <i>b_iso_in</i> elements.
+ */
+typedef union dev_dma_desc_sts {
+ /** raw register data */
+ uint32_t d32;
+ /** quadlet bits */
+ struct {
+ /** Received number of bytes */
+ unsigned bytes:16;
+
+ unsigned reserved16_22:7;
+ /** Multiple Transfer - only for OUT EPs */
+ unsigned mtrf:1;
+ /** Setup Packet received - only for OUT EPs */
+ unsigned sr:1;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Receive Status */
+ unsigned sts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b;
+
+#ifdef DWC_EN_ISOC
+ /** iso out quadlet bits */
+ struct {
+ /** Received number of bytes */
+ unsigned rxbytes:11;
+
+ unsigned reserved11:1;
+ /** Frame Number */
+ unsigned framenum:11;
+ /** Received ISO Data PID */
+ unsigned pid:2;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Receive Status */
+ unsigned rxsts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b_iso_out;
+
+ /** iso in quadlet bits */
+ struct {
+ /** Transmited number of bytes */
+ unsigned txbytes:12;
+ /** Frame Number */
+ unsigned framenum:11;
+ /** Transmited ISO Data PID */
+ unsigned pid:2;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** Short Packet */
+ unsigned sp:1;
+ /** Last */
+ unsigned l:1;
+ /** Transmit Status */
+ unsigned txsts:2;
+ /** Buffer Status */
+ unsigned bs:2;
+ } b_iso_in;
+#endif /* DWC_EN_ISOC */
+} dev_dma_desc_sts_t;
+
+/**
+ * DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct dwc_otg_dev_dma_desc {
+ /** DMA Descriptor status quadlet */
+ dev_dma_desc_sts_t status;
+ /** DMA Descriptor data buffer pointer */
+ uint32_t buf;
+} dwc_otg_dev_dma_desc_t;
+
+/* Host Mode Register Structures */
+
+/**
+ * The Host Global Registers structure defines the size and relative
+ * field offsets for the Host Mode Global Registers. Host Global
+ * Registers offsets 400h-7FFh.
+*/
+typedef struct dwc_otg_host_global_regs {
+ /** Host Configuration Register. <i>Offset: 400h</i> */
+ volatile uint32_t hcfg;
+ /** Host Frame Interval Register. <i>Offset: 404h</i> */
+ volatile uint32_t hfir;
+ /** Host Frame Number / Frame Remaining Register. <i>Offset: 408h</i> */
+ volatile uint32_t hfnum;
+ /** Reserved. <i>Offset: 40Ch</i> */
+ uint32_t reserved40C;
+ /** Host Periodic Transmit FIFO/ Queue Status Register. <i>Offset: 410h</i> */
+ volatile uint32_t hptxsts;
+ /** Host All Channels Interrupt Register. <i>Offset: 414h</i> */
+ volatile uint32_t haint;
+ /** Host All Channels Interrupt Mask Register. <i>Offset: 418h</i> */
+ volatile uint32_t haintmsk;
+ /** Host Frame List Base Address Register . <i>Offset: 41Ch</i> */
+ volatile uint32_t hflbaddr;
+} dwc_otg_host_global_regs_t;
+
+
+/**
+ * This union represents the bit fields in the Host Configuration Register.
+ * Read the register into the <i>d32</i> member then set/clear the bits using
+ * the <i>b</i>it elements. Write the <i>d32</i> member to the hcfg register.
+ */
+typedef union hcfg_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** FS/LS Phy Clock Select */
+ unsigned fslspclksel:2;
+#define DWC_HCFG_30_60_MHZ 0
+#define DWC_HCFG_48_MHZ 1
+#define DWC_HCFG_6_MHZ 2
+
+ /** FS/LS Only Support */
+ unsigned fslssupp:1;
+ unsigned reserved3_22:20;
+ /** Enable Scatter/gather DMA in Host mode */
+ unsigned descdma:1;
+ /** Frame List Entries */
+ unsigned frlisten:2;
+ /** Enable Periodic Scheduling */
+ unsigned perschedena:1;
+ /** Periodic Scheduling Enabled Status */
+ unsigned perschedstat:1;
+ } b;
+} hcfg_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfir_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned frint:16;
+ unsigned reserved:16;
+ } b;
+} hfir_data_t;
+
+/**
+ * This union represents the bit fields in the Host Frame Remaing/Number
+ * Register.
+ */
+typedef union hfnum_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned frnum:16;
+#define DWC_HFNUM_MAX_FRNUM 0x3FFF
+ unsigned frrem:16;
+ } b;
+} hfnum_data_t;
+
+typedef union hptxsts_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned ptxfspcavail:16;
+ unsigned ptxqspcavail:8;
+ /** Top of the Periodic Transmit Request Queue
+ * - bit 24 - Terminate (last entry for the selected channel)
+ * - bits 26:25 - Token Type
+ * - 2'b00 - Zero length
+ * - 2'b01 - Ping
+ * - 2'b10 - Disable
+ * - bits 30:27 - Channel Number
+ * - bit 31 - Odd/even microframe
+ */
+ unsigned ptxqtop_terminate:1;
+ unsigned ptxqtop_token:2;
+ unsigned ptxqtop_chnum:4;
+ unsigned ptxqtop_odd:1;
+ } b;
+} hptxsts_data_t;
+
+/**
+ * This union represents the bit fields in the Host Port Control and Status
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hprt0 register.
+ */
+typedef union hprt0_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned prtconnsts:1;
+ unsigned prtconndet:1;
+ unsigned prtena:1;
+ unsigned prtenchng:1;
+ unsigned prtovrcurract:1;
+ unsigned prtovrcurrchng:1;
+ unsigned prtres:1;
+ unsigned prtsusp:1;
+ unsigned prtrst:1;
+ unsigned reserved9:1;
+ unsigned prtlnsts:2;
+ unsigned prtpwr:1;
+ unsigned prttstctl:4;
+ unsigned prtspd:2;
+#define DWC_HPRT0_PRTSPD_HIGH_SPEED 0
+#define DWC_HPRT0_PRTSPD_FULL_SPEED 1
+#define DWC_HPRT0_PRTSPD_LOW_SPEED 2
+ unsigned reserved19_31:13;
+ } b;
+} hprt0_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ch0:1;
+ unsigned ch1:1;
+ unsigned ch2:1;
+ unsigned ch3:1;
+ unsigned ch4:1;
+ unsigned ch5:1;
+ unsigned ch6:1;
+ unsigned ch7:1;
+ unsigned ch8:1;
+ unsigned ch9:1;
+ unsigned ch10:1;
+ unsigned ch11:1;
+ unsigned ch12:1;
+ unsigned ch13:1;
+ unsigned ch14:1;
+ unsigned ch15:1;
+ unsigned reserved:16;
+ } b;
+
+ struct {
+ unsigned chint:16;
+ unsigned reserved:16;
+ } b2;
+} haint_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union haintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned ch0:1;
+ unsigned ch1:1;
+ unsigned ch2:1;
+ unsigned ch3:1;
+ unsigned ch4:1;
+ unsigned ch5:1;
+ unsigned ch6:1;
+ unsigned ch7:1;
+ unsigned ch8:1;
+ unsigned ch9:1;
+ unsigned ch10:1;
+ unsigned ch11:1;
+ unsigned ch12:1;
+ unsigned ch13:1;
+ unsigned ch14:1;
+ unsigned ch15:1;
+ unsigned reserved:16;
+ } b;
+
+ struct {
+ unsigned chint:16;
+ unsigned reserved:16;
+ } b2;
+} haintmsk_data_t;
+
+/**
+ * Host Channel Specific Registers. <i>500h-5FCh</i>
+ */
+typedef struct dwc_otg_hc_regs {
+ /** Host Channel 0 Characteristic Register. <i>Offset: 500h + (chan_num * 20h) + 00h</i> */
+ volatile uint32_t hcchar;
+ /** Host Channel 0 Split Control Register. <i>Offset: 500h + (chan_num * 20h) + 04h</i> */
+ volatile uint32_t hcsplt;
+ /** Host Channel 0 Interrupt Register. <i>Offset: 500h + (chan_num * 20h) + 08h</i> */
+ volatile uint32_t hcint;
+ /** Host Channel 0 Interrupt Mask Register. <i>Offset: 500h + (chan_num * 20h) + 0Ch</i> */
+ volatile uint32_t hcintmsk;
+ /** Host Channel 0 Transfer Size Register. <i>Offset: 500h + (chan_num * 20h) + 10h</i> */
+ volatile uint32_t hctsiz;
+ /** Host Channel 0 DMA Address Register. <i>Offset: 500h + (chan_num * 20h) + 14h</i> */
+ volatile uint32_t hcdma;
+ volatile uint32_t reserved;
+ /** Host Channel 0 DMA Buffer Address Register. <i>Offset: 500h + (chan_num * 20h) + 1Ch</i> */
+ volatile uint32_t hcdmab;
+} dwc_otg_hc_regs_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Characteristics
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+typedef union hcchar_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Maximum packet size in bytes */
+ unsigned mps:11;
+
+ /** Endpoint number */
+ unsigned epnum:4;
+
+ /** 0: OUT, 1: IN */
+ unsigned epdir:1;
+
+ unsigned reserved:1;
+
+ /** 0: Full/high speed device, 1: Low speed device */
+ unsigned lspddev:1;
+
+ /** 0: Control, 1: Isoc, 2: Bulk, 3: Intr */
+ unsigned eptype:2;
+
+ /** Packets per frame for periodic transfers. 0 is reserved. */
+ unsigned multicnt:2;
+
+ /** Device address */
+ unsigned devaddr:7;
+
+ /**
+ * Frame to transmit periodic transaction.
+ * 0: even, 1: odd
+ */
+ unsigned oddfrm:1;
+
+ /** Channel disable */
+ unsigned chdis:1;
+
+ /** Channel enable */
+ unsigned chen:1;
+ } b;
+} hcchar_data_t;
+
+typedef union hcsplt_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Port Address */
+ unsigned prtaddr:7;
+
+ /** Hub Address */
+ unsigned hubaddr:7;
+
+ /** Transaction Position */
+ unsigned xactpos:2;
+#define DWC_HCSPLIT_XACTPOS_MID 0
+#define DWC_HCSPLIT_XACTPOS_END 1
+#define DWC_HCSPLIT_XACTPOS_BEGIN 2
+#define DWC_HCSPLIT_XACTPOS_ALL 3
+
+ /** Do Complete Split */
+ unsigned compsplt:1;
+
+ /** Reserved */
+ unsigned reserved:14;
+
+ /** Split Enble */
+ unsigned spltena:1;
+ } b;
+} hcsplt_data_t;
+
+/**
+ * This union represents the bit fields in the Host All Interrupt
+ * Register.
+ */
+typedef union hcint_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ /** Transfer Complete */
+ unsigned xfercomp:1;
+ /** Channel Halted */
+ unsigned chhltd:1;
+ /** AHB Error */
+ unsigned ahberr:1;
+ /** STALL Response Received */
+ unsigned stall:1;
+ /** NAK Response Received */
+ unsigned nak:1;
+ /** ACK Response Received */
+ unsigned ack:1;
+ /** NYET Response Received */
+ unsigned nyet:1;
+ /** Transaction Err */
+ unsigned xacterr:1;
+ /** Babble Error */
+ unsigned bblerr:1;
+ /** Frame Overrun */
+ unsigned frmovrun:1;
+ /** Data Toggle Error */
+ unsigned datatglerr:1;
+ /** Buffer Not Available (only for DDMA mode) */
+ unsigned bna:1;
+ /** Exessive transaction error (only for DDMA mode) */
+ unsigned xcs_xact:1;
+ /** Frame List Rollover interrupt */
+ unsigned frm_list_roll:1;
+ /** Reserved */
+ unsigned reserved14_31:18;
+ } b;
+} hcint_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Interrupt Mask
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcintmsk register.
+ */
+typedef union hcintmsk_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ unsigned xfercompl:1;
+ unsigned chhltd:1;
+ unsigned ahberr:1;
+ unsigned stall:1;
+ unsigned nak:1;
+ unsigned ack:1;
+ unsigned nyet:1;
+ unsigned xacterr:1;
+ unsigned bblerr:1;
+ unsigned frmovrun:1;
+ unsigned datatglerr:1;
+ unsigned bna:1;
+ unsigned xcs_xact:1;
+ unsigned frm_list_roll:1;
+ unsigned reserved14_31:18;
+ } b;
+} hcintmsk_data_t;
+
+/**
+ * This union represents the bit fields in the Host Channel Transfer Size
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements. Write the <i>d32</i> member to the
+ * hcchar register.
+ */
+
+typedef union hctsiz_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Total transfer size in bytes */
+ unsigned xfersize:19;
+
+ /** Data packets to transfer */
+ unsigned pktcnt:10;
+
+ /**
+ * Packet ID for next data packet
+ * 0: DATA0
+ * 1: DATA2
+ * 2: DATA1
+ * 3: MDATA (non-Control), SETUP (Control)
+ */
+ unsigned pid:2;
+#define DWC_HCTSIZ_DATA0 0
+#define DWC_HCTSIZ_DATA1 2
+#define DWC_HCTSIZ_DATA2 1
+#define DWC_HCTSIZ_MDATA 3
+#define DWC_HCTSIZ_SETUP 3
+
+ /** Do PING protocol when 1 */
+ unsigned dopng:1;
+ } b;
+
+ /** register bits */
+ struct {
+ /** Scheduling information */
+ unsigned schinfo:8;
+
+ /** Number of transfer descriptors.
+ * Max value:
+ * 64 in general,
+ * 256 only for HS isochronous endpoint.
+ */
+ unsigned ntd:8;
+
+ /** Data packets to transfer */
+ unsigned reserved16_28:13;
+
+ /**
+ * Packet ID for next data packet
+ * 0: DATA0
+ * 1: DATA2
+ * 2: DATA1
+ * 3: MDATA (non-Control)
+ */
+ unsigned pid:2;
+
+ /** Do PING protocol when 1 */
+ unsigned dopng:1;
+ } b_ddma;
+} hctsiz_data_t;
+
+
+/**
+ * This union represents the bit fields in the Host DMA Address
+ * Register used in Descriptor DMA mode.
+ */
+typedef union hcdma_data {
+ /** raw register data */
+ uint32_t d32;
+ /** register bits */
+ struct {
+ unsigned reserved0_2:3;
+ /** Current Transfer Descriptor. Not used for ISOC */
+ unsigned ctd:8;
+ /** Start Address of Descriptor List */
+ unsigned dma_addr:21;
+ } b;
+} hcdma_data_t;
+
+/**
+ * This union represents the bit fields in the DMA Descriptor
+ * status quadlet for host mode. Read the quadlet into the <i>d32</i> member then
+ * set/clear the bits using the <i>b</i>it elements.
+ */
+typedef union host_dma_desc_sts {
+ /** raw register data */
+ uint32_t d32;
+ /** quadlet bits */
+
+ /* for non-isochronous */
+ struct {
+ /** Number of bytes */
+ unsigned n_bytes:17;
+ /** QTD offset to jump when Short Packet received - only for IN EPs */
+ unsigned qtd_offset:6;
+ /**
+ * Set to request the core to jump to alternate QTD if
+ * Short Packet received - only for IN EPs
+ */
+ unsigned a_qtd:1;
+ /**
+ * Setup Packet bit. When set indicates that buffer contains
+ * setup packet.
+ */
+ unsigned sup:1;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ /** End of List */
+ unsigned eol:1;
+ unsigned reserved27:1;
+ /** Rx/Tx Status */
+ unsigned sts:2;
+ #define DMA_DESC_STS_PKTERR 1
+ unsigned reserved30:1;
+ /** Active Bit */
+ unsigned a:1;
+ } b;
+ /* for isochronous */
+ struct {
+ /** Number of bytes */
+ unsigned n_bytes:12;
+ unsigned reserved12_24:13;
+ /** Interrupt On Complete */
+ unsigned ioc:1;
+ unsigned reserved26_27:2;
+ /** Rx/Tx Status */
+ unsigned sts:2;
+ unsigned reserved30:1;
+ /** Active Bit */
+ unsigned a:1;
+ } b_isoc;
+} host_dma_desc_sts_t;
+
+#define MAX_DMA_DESC_SIZE 131071
+#define MAX_DMA_DESC_NUM_GENERIC 64
+#define MAX_DMA_DESC_NUM_HS_ISOC 256
+#define MAX_FRLIST_EN_NUM 64
+/**
+ * Host-mode DMA Descriptor structure
+ *
+ * DMA Descriptor structure contains two quadlets:
+ * Status quadlet and Data buffer pointer.
+ */
+typedef struct dwc_otg_host_dma_desc {
+ /** DMA Descriptor status quadlet */
+ host_dma_desc_sts_t status;
+ /** DMA Descriptor data buffer pointer */
+ uint32_t buf;
+} dwc_otg_host_dma_desc_t;
+
+/** OTG Host Interface Structure.
+ *
+ * The OTG Host Interface Structure structure contains information
+ * needed to manage the DWC_otg controller acting in host mode. It
+ * represents the programming view of the host-specific aspects of the
+ * controller.
+ */
+typedef struct dwc_otg_host_if {
+ /** Host Global Registers starting at offset 400h. */
+ dwc_otg_host_global_regs_t *host_global_regs;
+#define DWC_OTG_HOST_GLOBAL_REG_OFFSET 0x400
+
+ /** Host Port 0 Control and Status Register */
+ volatile uint32_t *hprt0;
+#define DWC_OTG_HOST_PORT_REGS_OFFSET 0x440
+
+ /** Host Channel Specific Registers at offsets 500h-5FCh. */
+ dwc_otg_hc_regs_t *hc_regs[MAX_EPS_CHANNELS];
+#define DWC_OTG_HOST_CHAN_REGS_OFFSET 0x500
+#define DWC_OTG_CHAN_REGS_OFFSET 0x20
+
+ /* Host configuration information */
+ /** Number of Host Channels (range: 1-16) */
+ uint8_t num_host_channels;
+ /** Periodic EPs supported (0: no, 1: yes) */
+ uint8_t perio_eps_supported;
+ /** Periodic Tx FIFO Size (Only 1 host periodic Tx FIFO) */
+ uint16_t perio_tx_fifo_size;
+
+} dwc_otg_host_if_t;
+
+/**
+ * This union represents the bit fields in the Power and Clock Gating Control
+ * Register. Read the register into the <i>d32</i> member then set/clear the
+ * bits using the <i>b</i>it elements.
+ */
+typedef union pcgcctl_data {
+ /** raw register data */
+ uint32_t d32;
+
+ /** register bits */
+ struct {
+ /** Stop Pclk */
+ unsigned stoppclk:1;
+ /** Gate Hclk */
+ unsigned gatehclk:1;
+ /** Power Clamp */
+ unsigned pwrclmp:1;
+ /** Reset Power Down Modules */
+ unsigned rstpdwnmodule:1;
+ /** PHY Suspended */
+ unsigned physuspended:1;
+ /** Enable Sleep Clock Gating (Enbl_L1Gating) */
+ unsigned enbl_sleep_gating:1;
+ /** PHY In Sleep (PhySleep) */
+ unsigned phy_in_sleep:1;
+ /** Deep Sleep */
+ unsigned deep_sleep:1;
+
+ unsigned reserved31_8:24;
+ } b;
+} pcgcctl_data_t;
+
+#endif
diff --git a/include/usb.h b/include/usb.h
index 736730e..184c006 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -150,7 +150,8 @@ enum usb_init_type {
defined(CONFIG_USB_OMAP3) || defined(CONFIG_USB_DA8XX) || \
defined(CONFIG_USB_BLACKFIN) || defined(CONFIG_USB_AM35X) || \
defined(CONFIG_USB_MUSB_DSPS) || defined(CONFIG_USB_MUSB_AM35X) || \
- defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI)
+ defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined(CONFIG_USB_XHCI) || \
+ defined(CONFIG_USB_DWC2_OTG)
int usb_lowlevel_init(int index, enum usb_init_type init, void **controller);
int usb_lowlevel_stop(int index);
--
1.8.3.2
More information about the U-Boot
mailing list