blob: f1ef694204ff6178777aee5eadba0de9637ef56d [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <zircon/hw/usb.h>
#define MAX_EPS_CHANNELS 16
#define DWC_EP_IN_SHIFT 0
#define DWC_EP_OUT_SHIFT 16
#define DWC_EP_IN_MASK 0x0000ffff
#define DWC_EP_OUT_MASK 0xffff0000
#define DWC_EP_IS_IN(ep) ((ep) < 16)
#define DWC_EP_IS_OUT(ep) ((ep) >= 16)
#define DWC_MAX_EPS 32
// converts a USB endpoint address to 0 - 31 index
// in endpoints -> 0 - 15
// out endpoints -> 17 - 31 (16 is unused)
#define DWC_ADDR_TO_INDEX(addr) (((addr) & 0xF) + (16 * !((addr) & USB_DIR_IN)))
#define DWC_REG_DATA_FIFO_START 0x1000
#define DWC_REG_DATA_FIFO(regs, ep) ((volatile uint32_t*)((uint8_t*)regs + (ep + 1) * 0x1000))
typedef union {
uint32_t val;
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 reserved2 : 12;
uint32_t remmemsupp : 1;
uint32_t notialldmawrit : 1;
uint32_t AHBSingle : 1;
uint32_t reserved3 : 8;
};
} dwc_gahbcfg_t;
typedef union {
uint32_t val;
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 reserved1 : 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 indicator_complement : 1;
uint32_t indicator_pass_through : 1;
uint32_t ulpi_int_prot_dis : 1;
uint32_t ic_usb_cap : 1;
uint32_t ic_traffic_pull_remove : 1;
uint32_t tx_end_delay : 1;
uint32_t force_host_mode : 1;
uint32_t force_dev_mode : 1;
uint32_t reserved31 : 1;
};
} dwc_gusbcfg_t;
typedef union {
uint32_t val;
struct {
/* Core Soft Reset */
uint32_t csftrst : 1;
/* Hclk Soft Reset */
uint32_t hsftrst : 1;
/* Host Frame Counter Reset */
uint32_t hstfrm : 1;
/* In Token Sequence Learning Queue Flush */
uint32_t intknqflsh : 1;
/* RxFIFO Flush */
uint32_t rxfflsh : 1;
/* TxFIFO Flush */
uint32_t txfflsh : 1;
/* TxFIFO Number */
uint32_t txfnum : 5;
uint32_t reserved : 19;
/* DMA Request Signal */
uint32_t dmareq : 1;
/* AHB Master Idle */
uint32_t ahbidle : 1;
};
} dwc_grstctl_t;
typedef union {
uint32_t val;
struct {
uint32_t curmode : 1;
uint32_t modemismatch : 1;
uint32_t otgintr : 1;
uint32_t sof_intr : 1;
uint32_t rxstsqlvl : 1;
uint32_t nptxfempty : 1;
uint32_t ginnakeff : 1;
uint32_t goutnakeff : 1;
uint32_t ulpickint : 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 restoredone : 1;
uint32_t epmismatch : 1;
uint32_t inepintr : 1;
uint32_t outepintr : 1;
uint32_t incomplisoin : 1;
uint32_t incomplisoout : 1;
uint32_t fetsusp : 1;
uint32_t resetdet : 1;
uint32_t port_intr : 1;
uint32_t host_channel_intr : 1;
uint32_t ptxfempty : 1;
uint32_t lpmtranrcvd : 1;
uint32_t conidstschng : 1;
uint32_t disconnect : 1;
uint32_t sessreqintr : 1;
uint32_t wkupintr : 1;
};
} dwc_interrupts_t;
typedef union {
uint32_t val;
struct {
uint32_t epnum : 4;
uint32_t bcnt : 11;
uint32_t 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
uint32_t pktsts : 4;
uint32_t fn : 4;
uint32_t reserved : 7;
};
} dwc_grxstsp_t;
typedef union {
uint32_t val;
struct {
uint32_t mps : 11;
#define DWC_DEP0CTL_MPS_64 0
#define DWC_DEP0CTL_MPS_32 1
#define DWC_DEP0CTL_MPS_16 2
#define DWC_DEP0CTL_MPS_8 3
uint32_t nextep : 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;
};
} dwc_depctl_t;
typedef union {
uint32_t val;
struct {
/* Transfer size */
uint32_t xfersize : 19;
/* Packet Count */
uint32_t pktcnt : 10;
/* Multi Count */
uint32_t mc : 2;
uint32_t reserved : 1;
};
} dwc_deptsiz_t;
typedef union {
uint32_t val;
struct {
/* Transfer size */
uint32_t xfersize : 7;
uint32_t reserved : 12;
/* Packet Count */
uint32_t pktcnt : 2;
uint32_t reserved2 : 8;
/* Setup Packet Count */
uint32_t supcnt : 2;
uint32_t reserved3 : 1;
};
} dwc_deptsiz0_t;
typedef union {
uint32_t val;
struct {
/* Transfer complete mask */
uint32_t xfercompl : 1;
/* Endpoint disable mask */
uint32_t epdisabled : 1;
/* AHB Error mask */
uint32_t ahberr : 1;
/* TimeOUT Handshake mask (non-ISOC EPs) */
uint32_t timeout : 1;
/* IN Token received with TxF Empty mask */
uint32_t intktxfemp : 1;
/* IN Token Received with EP mismatch mask */
uint32_t intknepmis : 1;
/* IN Endpoint NAK Effective mask */
uint32_t inepnakeff : 1;
uint32_t reserved : 1;
uint32_t txfifoundrn : 1;
/* BNA Interrupt mask */
uint32_t bna : 1;
uint32_t reserved2 : 3;
/* BNA Interrupt mask */
uint32_t nak:1;
uint32_t reserved3 : 18;
};
} dwc_diepint_t;
typedef union {
uint32_t val;
struct {
/* Transfer complete */
uint32_t xfercompl : 1;
/* Endpoint disable */
uint32_t epdisabled : 1;
/* AHB Error */
uint32_t ahberr : 1;
/* Setup Phase Done (contorl EPs) */
uint32_t setup : 1;
/* OUT Token Received when Endpoint Disabled */
uint32_t outtknepdis : 1;
uint32_t stsphsercvd : 1;
/* Back-to-Back SETUP Packets Received */
uint32_t back2backsetup : 1;
uint32_t reserved : 1;
/* OUT packet Error */
uint32_t outpkterr : 1;
/* BNA Interrupt */
uint32_t bna : 1;
uint32_t reserved2 : 1;
/* Packet Drop Status */
uint32_t pktdrpsts : 1;
/* Babble Interrupt */
uint32_t babble : 1;
/* NAK Interrupt */
uint32_t nak : 1;
/* NYET Interrupt */
uint32_t nyet : 1;
/* Bit indicating setup packet received */
uint32_t sr : 1;
uint32_t reserved3 : 16;
};
} dwc_doepint_t;
typedef union {
uint32_t val;
struct {
uint32_t devspd : 2;
uint32_t nzstsouthshk : 1;
uint32_t ena32khzs : 1;
uint32_t devaddr : 7;
uint32_t perfrint : 2;
uint32_t endevoutnak : 1;
uint32_t reserved : 4;
uint32_t epmscnt : 5;
uint32_t descdma : 1;
uint32_t perschintvl : 2;
uint32_t resvalid : 6;
};
} dwc_dcfg_t;
typedef union {
uint32_t val;
struct {
/* Remote Wakeup */
uint32_t rmtwkupsig : 1;
/* Soft Disconnect */
uint32_t sftdiscon : 1;
/* Global Non-Periodic IN NAK Status */
uint32_t gnpinnaksts : 1;
/* Global OUT NAK Status */
uint32_t goutnaksts : 1;
/* Test Control */
uint32_t tstctl : 3;
/* Set Global Non-Periodic IN NAK */
uint32_t sgnpinnak : 1;
/* Clear Global Non-Periodic IN NAK */
uint32_t cgnpinnak : 1;
/* Set Global OUT NAK */
uint32_t sgoutnak : 1;
/* Clear Global OUT NAK */
uint32_t cgoutnak : 1;
/* Power-On Programming Done */
uint32_t pwronprgdone : 1;
/* Reserved */
uint32_t reserved : 1;
/* Global Multi Count */
uint32_t gmc : 2;
/* Ignore Frame Number for ISOC EPs */
uint32_t ifrmnum : 1;
/* NAK on Babble */
uint32_t nakonbble : 1;
/* Enable Continue on BNA */
uint32_t encontonbna : 1;
/* Enable deep sleep besl reject feature*/
uint32_t besl_reject : 1;
uint32_t reserved2 : 13;
};
} dwc_dctl_t;
typedef union {
uint32_t val;
struct {
/* Suspend Status */
uint32_t suspsts : 1;
/* Enumerated Speed */
uint32_t enumspd : 2;
/* Erratic Error */
uint32_t errticerr : 1;
uint32_t reserved : 4;
/* Frame or Microframe Number of the received SOF */
uint32_t soffn : 14;
uint32_t reserved2 : 10;
};
} dwc_dsts_t;
typedef struct {
/* Device IN Endpoint Control Register */
dwc_depctl_t diepctl;
uint32_t reserved;
/* Device IN Endpoint Interrupt Register */
dwc_diepint_t diepint;
uint32_t reserved2;
/* Device IN Endpoint Transfer Size */
dwc_deptsiz_t dieptsiz;
/* Device IN Endpoint DMA Address Register */
uint32_t diepdma;
/* Device IN Endpoint Transmit FIFO Status Register */
uint32_t dtxfsts;
/* Device IN Endpoint DMA Buffer Register */
uint32_t diepdmab;
} dwc_depin_t;
typedef struct {
/* Device OUT Endpoint Control Register */
dwc_depctl_t doepctl;
uint32_t reserved;
/* Device OUT Endpoint Interrupt Register */
dwc_doepint_t doepint;
uint32_t reserved2;
/* Device OUT Endpoint Transfer Size Register */
dwc_deptsiz_t doeptsiz;
/* Device OUT Endpoint DMA Address Register */
uint32_t doepdma;
uint32_t reserved3;
/* Device OUT Endpoint DMA Buffer Register */
uint32_t doepdmab;
} dwc_depout_t;
typedef union {
uint32_t val;
struct {
/** Stop Pclk */
uint32_t stoppclk:1;
/** Gate Hclk */
uint32_t gatehclk:1;
/** Power Clamp */
uint32_t pwrclmp:1;
/** Reset Power Down Modules */
uint32_t rstpdwnmodule:1;
/** Reserved */
uint32_t reserved:1;
/** Enable Sleep Clock Gating (Enbl_L1Gating) */
uint32_t enbl_sleep_gating:1;
/** PHY In Sleep (PhySleep) */
uint32_t phy_in_sleep:1;
/** Deep Sleep*/
uint32_t deep_sleep:1;
uint32_t resetaftsusp:1;
uint32_t restoremode:1;
uint32_t reserved10_12:3;
uint32_t ess_reg_restored:1;
uint32_t prt_clk_sel:2;
uint32_t port_power:1;
uint32_t max_xcvrselect:2;
uint32_t max_termsel:1;
uint32_t mac_dev_addr:7;
uint32_t p2hd_dev_enum_spd:2;
uint32_t p2hd_prt_spd:2;
uint32_t if_dev_mode:1;
};
} dwc_pcgcctl_t;
typedef union {
uint32_t val;
struct {
uint32_t nptxfspcavail:16;
uint32_t 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
*/
uint32_t nptxqtop_terminate:1;
uint32_t nptxqtop_token:2;
uint32_t nptxqtop_chnep:4;
uint32_t reserved:1;
};
} dwc_gnptxsts_t;
typedef union {
uint32_t val;
struct {
uint32_t startaddr : 16;
uint32_t depth : 16;
};
} dwc_fifosiz_t;
typedef volatile struct {
// OTG Control and Status Register
uint32_t gotgctl;
// OTG Interrupt Register
uint32_t gotgint;
// Core AHB Configuration Register
dwc_gahbcfg_t gahbcfg;
// Core USB Configuration Register
dwc_gusbcfg_t gusbcfg;
// Core Reset Register
dwc_grstctl_t grstctl;
// Core Interrupt Register
dwc_interrupts_t gintsts;
// Core Interrupt Mask Register
dwc_interrupts_t gintmsk;
// Receive Status Queue Read Register
uint32_t grxstsr;
// Receive Status Queue Read & POP Register
dwc_grxstsp_t grxstsp;
// Receive FIFO Size Register
uint32_t grxfsiz;
// Non Periodic Transmit FIFO Size Register
dwc_fifosiz_t gnptxfsiz;
// Non Periodic Transmit FIFO/Queue Status Register
dwc_gnptxsts_t gnptxsts;
// I2C Access Register
uint32_t gi2cctl;
// PHY Vendor Control Register
uint32_t gpvndctl;
// General Purpose Input/Output Register
uint32_t ggpio;
// User ID Register
uint32_t guid;
// Synopsys ID Register (Read Only)
uint32_t gsnpsid;
// User HW Config1 Register (Read Only)
uint32_t ghwcfg1;
// User HW Config2 Register (Read Only)
uint32_t ghwcfg2;
// User HW Config3 Register (Read Only)
uint32_t ghwcfg3;
// User HW Config4 Register (Read Only)
uint32_t ghwcfg4;
uint32_t reserved_030[(0x800 - 0x054) / sizeof(uint32_t)];
// Device Configuration Register
dwc_dcfg_t dcfg;
// Device Control Register
dwc_dctl_t dctl;
// Device Status Register
dwc_dsts_t dsts;
uint32_t unused;
// Device IN Endpoint Common Interrupt Mask Register
dwc_diepint_t diepmsk;
// Device OUT Endpoint Common Interrupt Mask Register
dwc_doepint_t doepmsk;
// Device All Endpoints Interrupt Register
uint32_t daint;
//Device All Endpoints Interrupt Mask Register
uint32_t daintmsk;
// Device IN Token Queue Read Register-1
uint32_t dtknqr1;
// Device IN Token Queue Read Register-2
uint32_t dtknqr2;
// Device VBUS discharge Register
uint32_t dvbusdis;
// Device VBUS pulse Register
uint32_t dvbuspulse;
// Device IN Token Queue Read Register-3 / Device Thresholding control register
uint32_t dtknqr3_dthrctl;
// Device IN Token Queue Read Register-4 / Device IN EPs empty Inr. Mask Register
uint32_t dtknqr4_fifoemptymsk;
// Device Each Endpoint Interrupt Register
uint32_t deachint;
//: Device Each Endpoint Interrupt Mask Register
uint32_t deachintmsk;
// Device Each In Endpoint Interrupt Mask Register
uint32_t diepeachintmsk[MAX_EPS_CHANNELS];
// Device Each Out Endpoint Interrupt Mask Register
uint32_t doepeachintmsk[MAX_EPS_CHANNELS];
uint32_t reserved_0x8C0[(0x900 - 0x8C0) / sizeof(uint32_t)];
dwc_depin_t depin[MAX_EPS_CHANNELS];
dwc_depout_t depout[MAX_EPS_CHANNELS];
uint32_t reserved_0xD00[(0xE00 - 0xD00) / sizeof(uint32_t)];
dwc_pcgcctl_t pcgcctl;
} dwc_regs_t;