Skip to content

Instantly share code, notes, and snippets.

@pamaury
Created July 12, 2013 11:55
Show Gist options
  • Save pamaury/5983912 to your computer and use it in GitHub Desktop.
Save pamaury/5983912 to your computer and use it in GitHub Desktop.
Original code from TheSeven
commit 63276ed0a61f6d7a362f70a3760b9fd332950472
Author: Amaury Pouly <[email protected]>
Date: Thu Mar 28 19:07:25 2013 +0100
Add synopsysotg driver from TheSeven
Change-Id: Ib2a3f343d7769929ad3301e3e77e564bc8a47770
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 8ba45af..903bec6 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -703,6 +703,7 @@ target/arm/usb-drv-arc.c
target/arm/as3525/usb-drv-as3525.c
#elif CONFIG_USBOTG == USBOTG_S3C6400X
target/arm/usb-s3c6400x.c
+target/arm/synopsisotg.h
#elif CONFIG_USBOTG == USBOTG_ISP1583
drivers/isp1583.c
#elif CONFIG_USBOTG == USBOTG_RK27XX
diff --git a/firmware/target/arm/synopsysotg.c b/firmware/target/arm/synopsysotg.c
new file mode 100644
index 0000000..6fc620d
--- /dev/null
+++ b/firmware/target/arm/synopsysotg.c
@@ -0,0 +1,437 @@
+#include "global.h"
+#include "core/synopsysotg/synopsysotg.h"
+#include "protocol/usb/usb.h"
+#include "sys/time.h"
+#include "sys/util.h"
+
+#ifndef SYNOPSYSOTG_AHB_BURST_LEN
+#define SYNOPSYSOTG_AHB_BURST_LEN 5
+#endif
+#ifndef SYNOPSYSOTG_AHB_THRESHOLD
+#define SYNOPSYSOTG_AHB_THRESHOLD 8
+#endif
+#ifndef SYNOPSYSOTG_TURNAROUND
+#define SYNOPSYSOTG_TURNAROUND 3
+#endif
+
+static void synopsysotg_flush_in_endpoint(const struct usb_instance* instance, int ep)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ if (data->core->inep_regs[ep].diepctl.b.epena)
+ {
+ // Urgh, someone was still babbling on our IN pipe, and now we have some
+ // old crap in the FIFO. Disable the endpoint, to make sure nobody will
+ // fetch any more old crap while we're trying to get rid of it.
+ synopsysotg_target_disable_irq(instance);
+ data->core->inep_regs[ep].diepctl.b.snak = 1;
+ while (!(data->core->inep_regs[ep].diepint.b.inepnakeff));
+ data->core->inep_regs[ep].diepctl.b.epdis = 1;
+ while (!(data->core->inep_regs[ep].diepint.b.epdisabled));
+ synopsysotg_target_enable_irq(instance);
+ // Wait for any DMA activity to stop, to make sure nobody will touch the FIFO.
+ while (!data->core->gregs.grstctl.b.ahbidle);
+ // Flush it all the way down!
+ union synopsysotg_grstctl grstctl = { .b = { .txfnum = ep, .txfflsh = 1 } };
+ data->core->gregs.grstctl = grstctl;
+ while (data->core->gregs.grstctl.b.txfflsh);
+ }
+ // Reset the transfer size register. Not strictly neccessary, but can't hurt.
+ data->core->inep_regs[ep].dieptsiz.d32 = 0;
+}
+
+static void synopsysotg_flush_ints(const struct usb_instance* instance)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ int i;
+ for (i = 0; i < 16; i++)
+ {
+ data->core->outep_regs[i].doepint = data->core->outep_regs[i].doepint;
+ data->core->inep_regs[i].diepint = data->core->inep_regs[i].diepint;
+ }
+ data->core->gregs.gintsts = data->core->gregs.gintsts;
+}
+
+void synopsysotg_start_rx(const struct usb_instance* instance, union usb_endpoint_number ep, void* buf, int size)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
+
+ // Find the appropriate set of endpoint registers
+ volatile struct synopsysotg_outepregs* regs = &data->core->outep_regs[ep.number];
+
+ // Calculate number of packets (if size == 0 an empty packet will be sent)
+ int maxpacket = regs->doepctl.b.mps;
+ int packets = (size + maxpacket - 1) / maxpacket;
+ if (!packets) packets = 1;
+
+ // Set up data desination
+ if (data->use_dma) regs->doepdma = buf;
+ else state->endpoints[ep.number].rxaddr = (uint32_t*)buf;
+ union synopsysotg_depxfrsiz deptsiz = { .b = { .pktcnt = packets, .xfersize = size } };
+ regs->doeptsiz = deptsiz;
+
+ // Flush CPU cache if necessary
+ if (data->use_dma) invalidate_dcache(buf, size);
+
+ // Enable the endpoint
+ union synopsysotg_depctl depctl = regs->doepctl;
+ depctl.b.epena = 1;
+ depctl.b.cnak = 1;
+ regs->doepctl = depctl;
+}
+
+void synopsysotg_start_tx(const struct usb_instance* instance, union usb_endpoint_number ep, const void* buf, int size)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
+
+ // Find the appropriate set of endpoint registers
+ volatile struct synopsysotg_inepregs* regs = &data->core->inep_regs[ep.number];
+
+ // Calculate number of packets (if size == 0 an empty packet will be sent)
+ int maxpacket = regs->diepctl.b.mps;
+ int packets = (size + maxpacket - 1) / maxpacket;
+ if (!packets) packets = 1;
+
+ // Set up data desination
+ if (data->use_dma) regs->diepdma = buf;
+ else state->endpoints[ep.number].txaddr = (uint32_t*)buf;
+ union synopsysotg_depxfrsiz deptsiz = { .b = { .pktcnt = packets, .xfersize = size } };
+ regs->dieptsiz = deptsiz;
+
+ // Flush CPU cache if necessary
+ if (data->use_dma) clean_dcache(buf, size);
+
+ // Enable the endpoint
+ union synopsysotg_depctl depctl = regs->diepctl;
+ depctl.b.epena = 1;
+ depctl.b.cnak = 1;
+ regs->diepctl = depctl;
+
+ // Start pushing data into the FIFO (must be done after enabling the endpoint)
+ if (!data->use_dma) data->core->dregs.diepempmsk.ep.in |= (1 << ep.number);
+}
+
+void synopsysotg_set_stall(const struct usb_instance* instance, union usb_endpoint_number ep, int stall)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
+ data->core->inep_regs[ep.number].diepctl.b.stall = !!stall;
+ else data->core->outep_regs[ep.number].doepctl.b.stall = !!stall;
+}
+
+void synopsysotg_set_address(const struct usb_instance* instance, uint8_t address)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ data->core->dregs.dcfg.b.devaddr = address;
+}
+
+void synopsysotg_unconfigure_ep(const struct usb_instance* instance, union usb_endpoint_number ep)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ union synopsysotg_depctl depctl = { .b = { .epdis = 1 } };
+ if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
+ {
+ synopsysotg_flush_in_endpoint(instance, ep.number);
+ data->core->inep_regs[ep.number].diepctl = depctl;
+ // Mask interrupts for this endpoint
+ data->core->dregs.daintmsk.ep.in &= ~(1 << ep.number);
+ }
+ else
+ {
+ // We can't really do much about in-flight OUT requests except for ignoring them.
+ data->core->outep_regs[ep.number].doeptsiz.d32 = 0;
+ data->core->outep_regs[ep.number].doepctl = depctl;
+ // Mask interrupts for this endpoint
+ data->core->dregs.daintmsk.ep.out &= ~(1 << ep.number);
+ }
+}
+
+void synopsysotg_configure_ep(const struct usb_instance* instance, union usb_endpoint_number ep,
+ enum usb_endpoint_type type, int maxpacket)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+
+ // Reset the endpoint, just in case someone left it in a dirty state.
+ synopsysotg_unconfigure_ep(instance, ep);
+
+ // Write the new configuration and unmask interrupts for the endpoint.
+ // Reset data toggle to DATA0, as required by the USB specification.
+ union synopsysotg_depctl depctl = { .b = { .usbactep = 1, .eptype = type, .mps = maxpacket, .txfnum = ep.number, .setd0pid = 1 } };
+ if (ep.direction == USB_ENDPOINT_DIRECTION_IN)
+ {
+ data->core->inep_regs[ep.number].diepctl = depctl;
+ data->core->dregs.daintmsk.ep.in |= (1 << ep.number);
+ }
+ else
+ {
+ data->core->outep_regs[ep.number].doepctl = depctl;
+ data->core->dregs.daintmsk.ep.out |= (1 << ep.number);
+ }
+}
+
+void synopsysotg_ep0_start_rx(const struct usb_instance* instance, int non_setup)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
+
+ // If we don't expect a non-SETUP packet, we can stall the OUT pipe,
+ // SETUP packets will ignore that.
+ if (!non_setup) data->core->outep_regs[0].doepctl.b.stall = 1;
+
+ // Set up data desination
+ if (data->use_dma) data->core->outep_regs[0].doepdma = instance->buffer;
+ else state->endpoints[0].rxaddr = (uint32_t*)instance->buffer;
+ union synopsysotg_dep0xfrsiz deptsiz = { .b = { .supcnt = 3, .pktcnt = !!non_setup, .xfersize = 64 } };
+ data->core->outep_regs[0].doeptsiz.d32 = deptsiz.d32;
+
+ // Flush CPU cache if necessary
+ if (data->use_dma) invalidate_dcache(instance->buffer, sizeof(instance->buffer));
+
+ // Enable the endpoint
+ union synopsysotg_depctl depctl = data->core->outep_regs[0].doepctl;
+ depctl.b.epena = 1;
+ depctl.b.cnak = 1;
+ data->core->outep_regs[0].doepctl = depctl;
+}
+
+void synopsysotg_ep0_start_tx(const struct usb_instance* instance, const void* buf, int len)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
+
+ if (len)
+ {
+ // Set up data source
+ if (data->use_dma) data->core->inep_regs[0].diepdma = buf;
+ else state->endpoints[0].txaddr = buf;
+ union synopsysotg_dep0xfrsiz deptsiz = { .b = { .pktcnt = (len + 63) >> 6, .xfersize = len } };
+ data->core->inep_regs[0].dieptsiz.d32 = deptsiz.d32;
+ }
+ else
+ {
+ // Set up the IN pipe for a zero-length packet
+ union synopsysotg_dep0xfrsiz deptsiz = { .b = { .pktcnt = 1 } };
+ data->core->inep_regs[0].dieptsiz.d32 = deptsiz.d32;
+ }
+
+ // Flush CPU cache if necessary
+ if (data->use_dma) clean_dcache(buf, len);
+
+ // Enable the endpoint
+ union synopsysotg_depctl depctl = data->core->inep_regs[0].diepctl;
+ depctl.b.epena = 1;
+ depctl.b.cnak = 1;
+ data->core->inep_regs[0].diepctl = depctl;
+
+ // Start pushing data into the FIFO (must be done after enabling the endpoint)
+ if (len && !data->use_dma) data->core->dregs.diepempmsk.ep.in |= 1;
+}
+
+static void synopsysotg_ep0_init(const struct usb_instance* instance)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+
+ // Make sure both EP0 pipes are active.
+ // (The hardware should take care of that, but who knows...)
+ union synopsysotg_depctl depctl = { .b = { .usbactep = 1 } };
+ data->core->outep_regs[0].doepctl = depctl;
+ data->core->inep_regs[0].diepctl = depctl;
+
+ // Prime EP0 for the first setup packet.
+ usb_ep0_expect_setup(instance);
+}
+
+void synopsysotg_irq(const struct usb_instance* instance)
+{
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+ struct synopsysotg_state* state = (struct synopsysotg_state*)instance->driver_state;
+
+ union synopsysotg_gintsts gintsts = data->core->gregs.gintsts;
+
+ if (gintsts.b.usbreset)
+ {
+ data->core->dregs.dcfg.b.devaddr = 0;
+ synopsysotg_ep0_init(instance);
+ usb_handle_bus_reset(instance, data->core->dregs.dsts.b.enumspd == 0);
+ }
+
+ if (gintsts.b.rxstsqlvl)
+ {
+ // Device to memory part of the "software DMA" implementation, used to receive data if use_dma == 0.
+ // Handle one packet at a time, the IRQ will re-trigger if there's something left.
+ union synopsysotg_grxfsts rxsts = data->core->gregs.grxstsp;
+ int ep = rxsts.b.chnum;
+ int words = (rxsts.b.bcnt + 3) >> 2;
+ while (words--) *state->endpoints[ep].rxaddr++ = data->core->dfifo[0][0];
+ }
+
+ if (gintsts.b.inepintr)
+ {
+ union synopsysotg_daint daint = data->core->dregs.daint;
+ int ep;
+ for (ep = 0; ep < 16; ep++)
+ if (daint.ep.in & (1 << ep))
+ {
+ union synopsysotg_diepintn epints = data->core->inep_regs[ep].diepint;
+ if (epints.b.emptyintr)
+ {
+ // Memory to device part of the "software DMA" implementation, used to transmit data if use_dma == 0.
+ union synopsysotg_depxfrsiz deptsiz = data->core->inep_regs[ep].dieptsiz;
+ if (!deptsiz.b.pktcnt) data->core->dregs.diepempmsk.ep.in &= ~(1 << ep);
+ else
+ {
+ // Push data into the TX FIFO until we don't have anything left or the FIFO would overflow.
+ int left = (deptsiz.b.xfersize + 3) >> 2;
+ while (left)
+ {
+ int words = data->core->inep_regs[ep].dtxfsts.b.txfspcavail;
+ if (words > left) words = left;
+ if (!words) break;
+ left -= words;
+ while (words--) data->core->dfifo[ep][0] = *state->endpoints[ep].txaddr++;
+ }
+ }
+ }
+ union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_IN, .number = ep };
+ int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
+ if (epints.b.timeout) usb_handle_timeout(instance, epnum, bytesleft);
+ if (epints.b.xfercompl) usb_handle_xfer_complete(instance, epnum, bytesleft);
+ data->core->inep_regs[ep].diepint = epints;
+ }
+ }
+
+ if (gintsts.b.outepintr)
+ {
+ union synopsysotg_daint daint = data->core->dregs.daint;
+ int ep;
+ for (ep = 0; ep < 16; ep++)
+ if (daint.ep.out & (1 << ep))
+ {
+ union synopsysotg_doepintn epints = data->core->outep_regs[ep].doepint;
+ union usb_endpoint_number epnum = { .direction = USB_ENDPOINT_DIRECTION_OUT, .number = ep };
+ if (epints.b.setup)
+ {
+ if (data->use_dma) invalidate_dcache(instance->buffer, sizeof(instance->buffer));
+ union synopsysotg_dep0xfrsiz deptsiz = { .d32 = data->core->outep_regs[0].doeptsiz.d32 };
+ int back2back = 3 - deptsiz.b.supcnt;
+ synopsysotg_flush_in_endpoint(instance, ep);
+ usb_handle_setup_received(instance, epnum, back2back);
+ }
+ else if (epints.b.xfercompl)
+ {
+ int bytesleft = data->core->inep_regs[ep].dieptsiz.b.xfersize;
+ usb_handle_xfer_complete(instance, epnum, bytesleft);
+ }
+ data->core->outep_regs[ep].doepint = epints;
+ }
+ }
+
+ data->core->gregs.gintsts = gintsts;
+}
+
+void synopsysotg_init(const struct usb_instance* instance)
+{
+ int i;
+
+ const struct synopsysotg_config* data = (const struct synopsysotg_config*)instance->driver_config;
+
+ // Disable IRQ during setup
+ synopsysotg_target_disable_irq(instance);
+
+ // Enable OTG clocks
+ synopsysotg_target_enable_clocks(instance);
+
+ // Enable PHY clocks
+ union synopsysotg_pcgcctl pcgcctl = { .b = {} };
+ data->core->pcgcctl = pcgcctl;
+
+ // Configure PHY type (must be done before reset)
+ union synopsysotg_gccfg gccfg = { .b = { .disablevbussensing = 1, .pwdn = 0 } };
+ data->core->gregs.gccfg = gccfg;
+ union synopsysotg_gusbcfg gusbcfg = { .b = { .force_dev = 1, .usbtrdtim = SYNOPSYSOTG_TURNAROUND } };
+ if (data->phy_16bit) gusbcfg.b.phyif = 1;
+ else if (data->phy_ulpi) gusbcfg.b.ulpi_utmi_sel = 1;
+ else gusbcfg.b.physel = 1;
+ data->core->gregs.gusbcfg = gusbcfg;
+
+ // Reset the whole USB core
+ union synopsysotg_grstctl grstctl = { .b = { .csftrst = 1 } };
+ udelay(100);
+ while (!data->core->gregs.grstctl.b.ahbidle);
+ data->core->gregs.grstctl = grstctl;
+ while (data->core->gregs.grstctl.b.csftrst);
+ while (!data->core->gregs.grstctl.b.ahbidle);
+
+ // Soft disconnect
+ union synopsysotg_dctl dctl = { .b = { .sftdiscon = 1 } };
+ data->core->dregs.dctl = dctl;
+
+ // Configure the core
+ union synopsysotg_gahbcfg gahbcfg = { .b = { .dmaenable = data->use_dma, .hburstlen = SYNOPSYSOTG_AHB_BURST_LEN, .glblintrmsk = 1 } };
+ if (data->disable_double_buffering)
+ {
+ gahbcfg.b.nptxfemplvl_txfemplvl = 1;
+ gahbcfg.b.ptxfemplvl = 1;
+ }
+ data->core->gregs.gahbcfg = gahbcfg;
+ data->core->gregs.gusbcfg = gusbcfg;
+ gccfg.b.pwdn = 1;
+ data->core->gregs.gccfg = gccfg;
+ union synopsysotg_dcfg dcfg = { .b = { .nzstsouthshk = 1 } };
+ data->core->dregs.dcfg = dcfg;
+
+ // Configure the FIFOs
+ if (data->use_dma)
+ {
+ union synopsysotg_dthrctl dthrctl = { .b = { .arb_park_en = 1, .rx_thr_en = 1, .iso_thr_en = 0, .non_iso_thr_en = 0,
+ .rx_thr_len = SYNOPSYSOTG_AHB_THRESHOLD } };
+ data->core->dregs.dthrctl = dthrctl;
+ }
+ int addr = data->fifosize;
+ for (i = 0; i < 16; i++)
+ {
+ int size = data->txfifosize[i];
+ addr -= size;
+ if (size)
+ {
+ union synopsysotg_txfsiz fsiz = { .b = { .startaddr = addr, .depth = size } };
+ if (!i) data->core->gregs.dieptxf0_hnptxfsiz = fsiz;
+ else data->core->gregs.dieptxf[i - 1] = fsiz;
+ }
+ }
+ union synopsysotg_rxfsiz fsiz = { .b = { .depth = addr } };
+ data->core->gregs.grxfsiz = fsiz;
+
+ // Set up interrupts
+ union synopsysotg_doepintn doepmsk = { .b = { .xfercompl = 1, .setup = 1 } };
+ data->core->dregs.doepmsk = doepmsk;
+ union synopsysotg_diepintn diepmsk = { .b = { .xfercompl = 1, .timeout = 1 } };
+ data->core->dregs.diepmsk = diepmsk;
+ data->core->dregs.diepempmsk.d32 = 0;
+ union synopsysotg_daint daintmsk = { .ep = { .in = 0b0000000000000001, .out = 0b0000000000000001 } };
+ data->core->dregs.daintmsk = daintmsk;
+ union synopsysotg_gintmsk gintmsk = { .b = { .usbreset = 1, .outepintr = 1, .inepintr = 1 } };
+ if (!data->use_dma) gintmsk.b.rxstsqlvl = 1;
+ data->core->gregs.gintmsk = gintmsk;
+ synopsysotg_flush_ints(instance);
+ synopsysotg_target_clear_irq(instance);
+ synopsysotg_target_enable_irq(instance);
+
+ // Soft reconnect
+ dctl.b.sftdiscon = 0;
+ data->core->dregs.dctl = dctl;
+}
+
+const struct usb_driver synopsysotg_driver =
+{
+ .init = synopsysotg_init,
+ .ep0_start_rx = synopsysotg_ep0_start_rx,
+ .ep0_start_tx = synopsysotg_ep0_start_tx,
+ .start_rx = synopsysotg_start_rx,
+ .start_tx = synopsysotg_start_tx,
+ .set_stall = synopsysotg_set_stall,
+ .set_address = synopsysotg_set_address,
+ .configure_ep = synopsysotg_configure_ep,
+ .unconfigure_ep = synopsysotg_unconfigure_ep,
+};
diff --git a/firmware/target/arm/synopsysotg.h b/firmware/target/arm/synopsysotg.h
new file mode 100644
index 0000000..a335115
--- /dev/null
+++ b/firmware/target/arm/synopsysotg.h
@@ -0,0 +1,39 @@
+#ifndef __CORE_SYNOPSYSOTG_SYNOPSYSOTG_H__
+#define __CORE_SYNOPSYSOTG_SYNOPSYSOTG_H__
+
+#include "global.h"
+#include "protocol/usb/usb.h"
+#include "core/synopsysotg/regs.h"
+
+struct __attribute__((packed,aligned(4))) synopsysotg_config
+{
+ volatile struct synopsysotg_core_regs* core;
+ uint32_t phy_16bit : 1;
+ uint32_t phy_ulpi : 1;
+ uint32_t use_dma : 1;
+ uint32_t disable_double_buffering : 1;
+ uint32_t reserved0 : 4;
+ uint8_t reserved1;
+ uint16_t fifosize;
+ uint16_t txfifosize[16];
+};
+
+struct __attribute__((packed,aligned(4))) synopsysotg_state
+{
+ int dummy[0];
+ struct
+ {
+ uint32_t* rxaddr;
+ const uint32_t* txaddr;
+ } endpoints[];
+};
+
+extern const struct usb_driver synopsysotg_driver;
+
+extern void synopsysotg_irq(const struct usb_instance* instance);
+extern void synopsysotg_target_enable_clocks(const struct usb_instance* instance);
+extern void synopsysotg_target_enable_irq(const struct usb_instance* instance);
+extern void synopsysotg_target_disable_irq(const struct usb_instance* instance);
+extern void synopsysotg_target_clear_irq(const struct usb_instance* instance);
+
+#endif
diff --git a/firmware/target/arm/synopsysotg_regs.h b/firmware/target/arm/synopsysotg_regs.h
new file mode 100644
index 0000000..476bae3
--- /dev/null
+++ b/firmware/target/arm/synopsysotg_regs.h
@@ -0,0 +1,838 @@
+#ifndef __CORESYNOPSYSOTG_REGS_H__
+#define __CORESYNOPSYSOTG_REGS_H__
+
+#include "global.h"
+
+
+union synopsysotg_gotgctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t sesreqscs :1;
+ uint32_t sesreq :1;
+ uint32_t reserved2_7 :6;
+ uint32_t hstnegscs :1;
+ uint32_t hnpreq :1;
+ uint32_t hstsethnpen :1;
+ uint32_t devhnpen :1;
+ uint32_t reserved12_15 :4;
+ uint32_t conidsts :1;
+ uint32_t reserved17 :1;
+ uint32_t asesvld :1;
+ uint32_t bsesvld :1;
+ uint32_t currmod :1;
+ uint32_t reserved21_31 :11;
+ } b;
+};
+
+union synopsysotg_gotgint
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t reserved0_1 :2;
+ uint32_t sesenddet :1;
+ uint32_t reserved3_7 :5;
+ uint32_t sesreqsucstschng :1;
+ uint32_t hstnegsucstschng :1;
+ uint32_t reserver10_16 :7;
+ uint32_t hstnegdet :1;
+ uint32_t adevtoutchng :1;
+ uint32_t debdone :1;
+ uint32_t reserved31_20 :12;
+ } b;
+};
+
+union synopsysotg_gahbcfg
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t glblintrmsk :1;
+ uint32_t hburstlen :4;
+ uint32_t dmaenable :1;
+ uint32_t reserved :1;
+ uint32_t nptxfemplvl_txfemplvl :1;
+ uint32_t ptxfemplvl :1;
+ uint32_t reserved9_31 :23;
+ } b;
+};
+
+union synopsysotg_gusbcfg
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t toutcal :3;
+ uint32_t phyif :1;
+ uint32_t ulpi_utmi_sel :1;
+ uint32_t fsintf :1;
+ uint32_t physel :1;
+ uint32_t ddrsel :1;
+ uint32_t srpcap :1;
+ uint32_t hnpcap :1;
+ uint32_t usbtrdtim :4;
+ uint32_t nptxfrwnden :1;
+ uint32_t phylpwrclksel :1;
+ uint32_t otgutmifssel :1;
+ uint32_t ulpi_fsls :1;
+ uint32_t ulpi_auto_res :1;
+ uint32_t ulpi_clk_sus_m :1;
+ uint32_t ulpi_ext_vbus_drv :1;
+ uint32_t ulpi_int_vbus_indicator :1;
+ uint32_t term_sel_dl_pulse :1;
+ uint32_t reserved :6;
+ uint32_t force_host :1;
+ uint32_t force_dev :1;
+ uint32_t corrupt_tx :1;
+ } b;
+};
+
+union synopsysotg_grstctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t csftrst :1;
+ uint32_t hsftrst :1;
+ uint32_t hstfrm :1;
+ uint32_t intknqflsh :1;
+ uint32_t rxfflsh :1;
+ uint32_t txfflsh :1;
+ uint32_t txfnum :5;
+ uint32_t reserved11_29 :19;
+ uint32_t dmareq :1;
+ uint32_t ahbidle :1;
+ } b;
+};
+
+union synopsysotg_gintmsk
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t reserved0 :1;
+ uint32_t modemismatch :1;
+ uint32_t otgintr :1;
+ uint32_t sofintr :1;
+ uint32_t rxstsqlvl :1;
+ uint32_t nptxfempty :1;
+ uint32_t ginnakeff :1;
+ uint32_t goutnakeff :1;
+ uint32_t reserved8 :1;
+ uint32_t i2cintr :1;
+ uint32_t erlysuspend :1;
+ uint32_t usbsuspend :1;
+ uint32_t usbreset :1;
+ uint32_t enumdone :1;
+ uint32_t isooutdrop :1;
+ uint32_t eopframe :1;
+ uint32_t reserved16 :1;
+ uint32_t epmismatch :1;
+ uint32_t inepintr :1;
+ uint32_t outepintr :1;
+ uint32_t incomplisoin :1;
+ uint32_t incomplisoout :1;
+ uint32_t reserved22_23 :2;
+ uint32_t portintr :1;
+ uint32_t hcintr :1;
+ uint32_t ptxfempty :1;
+ uint32_t reserved27 :1;
+ uint32_t conidstschng :1;
+ uint32_t disconnect :1;
+ uint32_t sessreqintr :1;
+ uint32_t wkupintr :1;
+ } b;
+};
+
+union synopsysotg_gintsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t curmode :1;
+ uint32_t modemismatch :1;
+ uint32_t otgintr :1;
+ uint32_t sofintr :1;
+ uint32_t rxstsqlvl :1;
+ uint32_t nptxfempty :1;
+ uint32_t ginnakeff :1;
+ uint32_t goutnakeff :1;
+ uint32_t reserved8 :1;
+ uint32_t i2cintr :1;
+ uint32_t erlysuspend :1;
+ uint32_t usbsuspend :1;
+ uint32_t usbreset :1;
+ uint32_t enumdone :1;
+ uint32_t isooutdrop :1;
+ uint32_t eopframe :1;
+ uint32_t intimerrx :1;
+ uint32_t epmismatch :1;
+ uint32_t inepintr :1;
+ uint32_t outepintr :1;
+ uint32_t incomplisoin :1;
+ uint32_t incomplisoout :1;
+ uint32_t reserved22_23 :2;
+ uint32_t portintr :1;
+ uint32_t hcintr :1;
+ uint32_t ptxfempty :1;
+ uint32_t reserved27 :1;
+ uint32_t conidstschng :1;
+ uint32_t disconnect :1;
+ uint32_t sessreqintr :1;
+ uint32_t wkupintr :1;
+ } b;
+};
+
+union synopsysotg_drxsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t epnum :4;
+ uint32_t bcnt :11;
+ uint32_t dpid :2;
+ uint32_t pktsts :4;
+ uint32_t fn :4;
+ uint32_t reserved :7;
+ } b;
+};
+
+union synopsysotg_grxfsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t chnum :4;
+ uint32_t bcnt :11;
+ uint32_t dpid :2;
+ uint32_t pktsts :4;
+ uint32_t reserved :11;
+ } b;
+};
+
+union synopsysotg_txfsiz
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t startaddr :16;
+ uint32_t depth :16;
+ } b;
+};
+
+union synopsysotg_rxfsiz
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t depth :16;
+ uint32_t reserved :16;
+ } b;
+};
+
+union synopsysotg_hnptxsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t nptxfspcavail :16;
+ uint32_t nptxqspcavail :8;
+ uint32_t nptxqtop_terminate :1;
+ uint32_t nptxqtop_timer :2;
+ uint32_t nptxqtop :2;
+ uint32_t chnum :2;
+ uint32_t reserved :1;
+ } b;
+};
+
+union synopsysotg_dtxfstsn
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t txfspcavail :16;
+ uint32_t reserved :16;
+ } b;
+};
+
+union synopsysotg_gi2cctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t rwdata :8;
+ uint32_t regaddr :8;
+ uint32_t addr :7;
+ uint32_t i2cen :1;
+ uint32_t ack :1;
+ uint32_t i2csuspctl :1;
+ uint32_t i2cdevaddr :2;
+ uint32_t dat_se0 :1;
+ uint32_t reserved :1;
+ uint32_t rw :1;
+ uint32_t bsydne :1;
+ } b;
+};
+
+union synopsysotg_gccfg
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t reserved_in :16;
+ uint32_t pwdn :1;
+ uint32_t i2cifen :1;
+ uint32_t vbussensinga :1;
+ uint32_t vbussensingb :1;
+ uint32_t sofouten :1;
+ uint32_t disablevbussensing :1;
+ uint32_t reserved_out :10;
+ } b;
+};
+
+union synopsysotg_ghwcfg1
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t ep0 :2;
+ uint32_t ep1 :2;
+ uint32_t ep2 :2;
+ uint32_t ep3 :2;
+ uint32_t ep4 :2;
+ uint32_t ep5 :2;
+ uint32_t ep6 :2;
+ uint32_t ep7 :2;
+ uint32_t ep8 :2;
+ uint32_t ep9 :2;
+ uint32_t ep10 :2;
+ uint32_t ep11 :2;
+ uint32_t ep12 :2;
+ uint32_t ep13 :2;
+ uint32_t ep14 :2;
+ uint32_t ep15 :2;
+ } b;
+};
+
+union synopsysotg_ghwcfg2
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t otgmode :3;
+ uint32_t otgarch :2;
+ uint32_t singpnt :1;
+ uint32_t hsphytype :2;
+ uint32_t fsphytype :2;
+ uint32_t numdeveps :4;
+ uint32_t numhstchnl :4;
+ uint32_t periosupport :1;
+ uint32_t dynfifosizing :1;
+ uint32_t reserved_20_21 :2;
+ uint32_t nptxqdepth :2;
+ uint32_t ptxqdepth :2;
+ uint32_t tknqdepth :5;
+ uint32_t reserved_31_31 :1;
+ } b;
+};
+
+union synopsysotg_ghwcfg3
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfersizewidth :4;
+ uint32_t pktsizewidth :3;
+ uint32_t otgen :1;
+ uint32_t i2c_selection :1;
+ uint32_t vendor_control_interface_support :1;
+ uint32_t optfeature :1;
+ uint32_t rsttype :1;
+ uint32_t ahbphysync :1;
+ uint32_t reserved_13_15 :3;
+ uint32_t dfifodepth :16;
+ } b;
+};
+
+union synopsysotg_ghwcfg4
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t numdevperioeps :4;
+ uint32_t enablepwropt :1;
+ uint32_t ahbfreq :1;
+ uint32_t reserved_6_13 :8;
+ uint32_t phydatawidth :2;
+ uint32_t numctleps :4;
+ uint32_t iddgfltr :1;
+ uint32_t vbusvalidfltr :1;
+ uint32_t avalidfltr :1;
+ uint32_t bvalidfltr :1;
+ uint32_t sessendfltr :1;
+ uint32_t endedtrfifo :1;
+ uint32_t numdevmodinend :4;
+ uint32_t reserved_30_31 :2;
+ } b;
+};
+
+union synopsysotg_dcfg
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t devspd :2;
+ uint32_t nzstsouthshk :1;
+ uint32_t reserved3 :1;
+ uint32_t devaddr :7;
+ uint32_t perfrint :2;
+ uint32_t reserved13_17 :5;
+ uint32_t epmscnt :4;
+ } b;
+};
+
+union synopsysotg_dctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t rmtwkupsig :1;
+ uint32_t sftdiscon :1;
+ uint32_t gnpinnaksts :1;
+ uint32_t goutnaksts :1;
+ uint32_t tstctl :3;
+ uint32_t sgnpinnak :1;
+ uint32_t cgnpinnak :1;
+ uint32_t sgoutnak :1;
+ uint32_t cgoutnak :1;
+ uint32_t reserved :21;
+ } b;
+};
+
+union synopsysotg_dsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t suspsts :1;
+ uint32_t enumspd :2;
+ uint32_t errticerr :1;
+ uint32_t reserved4_7 :4;
+ uint32_t soffn :14;
+ uint32_t reserved22_31 :10;
+ } b;
+};
+
+union synopsysotg_diepintn
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfercompl :1;
+ uint32_t epdisabled :1;
+ uint32_t ahberr :1;
+ uint32_t timeout :1;
+ uint32_t intktxfemp :1;
+ uint32_t intknepmis :1;
+ uint32_t inepnakeff :1;
+ uint32_t emptyintr :1;
+ uint32_t txfifoundrn :1;
+ uint32_t reserved08_31 :23;
+ } b;
+};
+
+union synopsysotg_doepintn
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfercompl :1;
+ uint32_t epdisabled :1;
+ uint32_t ahberr :1;
+ uint32_t setup :1;
+ uint32_t reserved04_31 :28;
+ } b;
+};
+
+union synopsysotg_daint
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t in :16;
+ uint32_t out :16;
+ } ep;
+};
+
+union synopsysotg_dthrctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t non_iso_thr_en :1;
+ uint32_t iso_thr_en :1;
+ uint32_t tx_thr_len :9;
+ uint32_t reserved11_15 :5;
+ uint32_t rx_thr_en :1;
+ uint32_t rx_thr_len :9;
+ uint32_t reserved26 :1;
+ uint32_t arb_park_en :1;
+ uint32_t reserved28_31 :4;
+ } b;
+};
+
+union synopsysotg_depctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t mps :11;
+ uint32_t reserved :4;
+ uint32_t usbactep :1;
+ uint32_t dpid :1;
+ uint32_t naksts :1;
+ uint32_t eptype :2;
+ uint32_t snp :1;
+ uint32_t stall :1;
+ uint32_t txfnum :4;
+ uint32_t cnak :1;
+ uint32_t snak :1;
+ uint32_t setd0pid :1;
+ uint32_t setd1pid :1;
+ uint32_t epdis :1;
+ uint32_t epena :1;
+ } b;
+};
+union synopsysotg_depxfrsiz
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfersize :19;
+ uint32_t pktcnt :10;
+ uint32_t mc :2;
+ uint32_t reserved :1;
+ } b;
+};
+
+union synopsysotg_dep0xfrsiz
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfersize :7;
+ uint32_t reserved7_18 :12;
+ uint32_t pktcnt :2;
+ uint32_t reserved21_28 :8;
+ uint32_t supcnt :2;
+ uint32_t reserved31;
+ } b;
+};
+
+union synopsysotg_hcfg
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t fslspclksel :2;
+ uint32_t fslssupp :1;
+ } b;
+};
+
+union synopsysotg_hfrmintrvl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t frint :16;
+ uint32_t reserved :16;
+ } b;
+};
+
+union synopsysotg_hfnum
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t frnum :16;
+ uint32_t frrem :16;
+ } b;
+};
+
+union synopsysotg_hptxsts
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t ptxfspcavail :16;
+ uint32_t ptxqspcavail :8;
+ uint32_t ptxqtop_terminate :1;
+ uint32_t ptxqtop_timer :2;
+ uint32_t ptxqtop :2;
+ uint32_t chnum :2;
+ uint32_t ptxqtop_odd :1;
+ } b;
+};
+
+union synopsysotg_hprt0
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t prtconnsts :1;
+ uint32_t prtconndet :1;
+ uint32_t prtena :1;
+ uint32_t prtenchng :1;
+ uint32_t prtovrcurract :1;
+ uint32_t prtovrcurrchng :1;
+ uint32_t prtres :1;
+ uint32_t prtsusp :1;
+ uint32_t prtrst :1;
+ uint32_t reserved9 :1;
+ uint32_t prtlnsts :2;
+ uint32_t prtpwr :1;
+ uint32_t prttstctl :4;
+ uint32_t prtspd :2;
+ uint32_t reserved19_31 :13;
+ } b;
+};
+
+union synopsysotg_haint
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t chint :16;
+ uint32_t reserved :16;
+ } b;
+};
+
+union synopsysotg_haintmsk
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t chint :16;
+ uint32_t reserved :16;
+ } b;
+};
+
+union synopsysotg_hcchar
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t mps :11;
+ uint32_t epnum :4;
+ uint32_t epdir :1;
+ uint32_t reserved :1;
+ uint32_t lspddev :1;
+ uint32_t eptype :2;
+ uint32_t multicnt :2;
+ uint32_t devaddr :7;
+ uint32_t oddfrm :1;
+ uint32_t chdis :1;
+ uint32_t chen :1;
+ } b;
+};
+
+union synopsysotg_hcsplt
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t prtaddr :7;
+ uint32_t hubaddr :7;
+ uint32_t xactpos :2;
+ uint32_t compsplt :1;
+ uint32_t reserved :14;
+ uint32_t spltena :1;
+ } b;
+};
+
+union synopsysotg_hcintn
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfercompl :1;
+ uint32_t chhltd :1;
+ uint32_t ahberr :1;
+ uint32_t stall :1;
+ uint32_t nak :1;
+ uint32_t ack :1;
+ uint32_t nyet :1;
+ uint32_t xacterr :1;
+ uint32_t bblerr :1;
+ uint32_t frmovrun :1;
+ uint32_t datatglerr :1;
+ uint32_t reserved :21;
+ } b;
+};
+
+union synopsysotg_hctsizn
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfersize :19;
+ uint32_t pktcnt :10;
+ uint32_t pid :2;
+ uint32_t dopng :1;
+ } b;
+};
+
+union synopsysotg_hcgintmsk
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t xfercompl :1;
+ uint32_t chhltd :1;
+ uint32_t ahberr :1;
+ uint32_t stall :1;
+ uint32_t nak :1;
+ uint32_t ack :1;
+ uint32_t nyet :1;
+ uint32_t xacterr :1;
+ uint32_t bblerr :1;
+ uint32_t frmovrun :1;
+ uint32_t datatglerr :1;
+ uint32_t reserved :21;
+ } b;
+};
+
+union synopsysotg_pcgcctl
+{
+ uint32_t d32;
+ struct
+ {
+ uint32_t stoppclk :1;
+ uint32_t gatehclk :1;
+ uint32_t reserved :30;
+ } b;
+};
+
+struct synopsysotg_gregs
+{
+ volatile union synopsysotg_gotgctl gotgctl;
+ volatile union synopsysotg_gotgint gotgint;
+ volatile union synopsysotg_gahbcfg gahbcfg;
+ volatile union synopsysotg_gusbcfg gusbcfg;
+ volatile union synopsysotg_grstctl grstctl;
+ volatile union synopsysotg_gintsts gintsts;
+ volatile union synopsysotg_gintmsk gintmsk;
+ volatile union synopsysotg_grxfsts grxstsr;
+ volatile union synopsysotg_grxfsts grxstsp;
+ volatile union synopsysotg_rxfsiz grxfsiz;
+ volatile union synopsysotg_txfsiz dieptxf0_hnptxfsiz;
+ volatile union synopsysotg_hnptxsts hnptxsts;
+ volatile union synopsysotg_gi2cctl gi2cctl;
+ volatile uint32_t reserved34;
+ volatile union synopsysotg_gccfg gccfg;
+ volatile uint32_t cid;
+ volatile uint32_t gsnpsid;
+ volatile union synopsysotg_ghwcfg1 ghwcfg1;
+ volatile union synopsysotg_ghwcfg2 ghwcfg2;
+ volatile union synopsysotg_ghwcfg3 ghwcfg3;
+ volatile union synopsysotg_ghwcfg4 ghwcfg4;
+ volatile uint32_t glpmcfg;
+ volatile uint32_t reserved58[42];
+ volatile union synopsysotg_txfsiz hptxfsiz;
+ volatile union synopsysotg_txfsiz dieptxf[15];
+};
+
+struct synopsysotg_dregs
+{
+ volatile union synopsysotg_dcfg dcfg;
+ volatile union synopsysotg_dctl dctl;
+ volatile union synopsysotg_dsts dsts;
+ volatile uint32_t reserved0c;
+ volatile union synopsysotg_diepintn diepmsk;
+ volatile union synopsysotg_doepintn doepmsk;
+ volatile union synopsysotg_daint daint;
+ volatile union synopsysotg_daint daintmsk;
+ volatile uint32_t reserved20;
+ volatile uint32_t reserved9;
+ volatile uint32_t dvbusdis;
+ volatile uint32_t dvbuspulse;
+ volatile union synopsysotg_dthrctl dthrctl;
+ volatile union synopsysotg_daint diepempmsk;
+ volatile union synopsysotg_daint deachint;
+ volatile union synopsysotg_daint deachmsk;
+ volatile union synopsysotg_diepintn dinep1msk;
+ volatile uint32_t reserved44[15];
+ volatile union synopsysotg_doepintn doutep1msk;
+};
+
+struct synopsysotg_inepregs
+{
+ volatile union synopsysotg_depctl diepctl;
+ volatile uint32_t reserved04;
+ volatile union synopsysotg_diepintn diepint;
+ volatile uint32_t reserved0c;
+ volatile union synopsysotg_depxfrsiz dieptsiz;
+ volatile const void* diepdma;
+ volatile union synopsysotg_dtxfstsn dtxfsts;
+ volatile uint32_t reserved18;
+};
+
+struct synopsysotg_outepregs
+{
+ volatile union synopsysotg_depctl doepctl;
+ volatile uint32_t doutepfrm;
+ volatile union synopsysotg_doepintn doepint;
+ volatile uint32_t reserved0c;
+ volatile union synopsysotg_depxfrsiz doeptsiz;
+ volatile void* doepdma;
+ volatile uint32_t reserved18[2];
+};
+
+struct synopsysotg_hregs
+{
+ volatile union synopsysotg_hcfg hcfg;
+ volatile uint32_t hfir;
+ volatile union synopsysotg_hfnum hfnum;
+ volatile uint32_t reserved40c;
+ volatile union synopsysotg_hptxsts hptxsts;
+ volatile union synopsysotg_haint haint;
+ volatile union synopsysotg_haintmsk haintmsk;
+};
+
+struct synopsysotg_hc_regs
+{
+ volatile union synopsysotg_hcchar hcchar;
+ volatile union synopsysotg_hcsplt hcsplt;
+ volatile union synopsysotg_hcintn hcint;
+ volatile union synopsysotg_hcintn hcgintmsk;
+ volatile union synopsysotg_hctsizn hctsiz;
+ volatile void* hcdma;
+ volatile uint32_t reserved[2];
+};
+
+struct synopsysotg_core_regs
+{
+ volatile struct synopsysotg_gregs gregs;
+ volatile uint32_t reserved140[176];
+ volatile struct synopsysotg_hregs hregs;
+ volatile uint32_t reserved41c[9];
+ volatile union synopsysotg_hprt0 hprt0;
+ volatile uint32_t reserved444[47];
+ volatile struct synopsysotg_hc_regs hc_regs[16];
+ volatile uint32_t reserved700[64];
+ volatile struct synopsysotg_dregs dregs;
+ volatile uint32_t reserved884[31];
+ volatile struct synopsysotg_inepregs inep_regs[16];
+ volatile struct synopsysotg_outepregs outep_regs[16];
+ volatile uint32_t reservedd00[64];
+ volatile union synopsysotg_pcgcctl pcgcctl;
+ volatile uint32_t reservede04[127];
+ volatile uint32_t dfifo[16][1024];
+ volatile uint32_t reserved11000[15360];
+ volatile uint32_t rawfifo[32768];
+};
+
+
+#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment