/* * USB host driver for BCM2835 * Synopsis DesignWare Core USB 2.0 OTG controller * * Device register definitions */ typedef unsigned int Reg; typedef struct Dwcregs Dwcregs; typedef struct Hostchan Hostchan; enum { Maxchans = 16, /* actual number of channels in ghwcfg2 */ }; struct Dwcregs { /* Core global registers 0x000-0x140 */ Reg gotgctl; /* OTG Control and Status */ Reg gotgint; /* OTG Interrupt */ Reg gahbcfg; /* Core AHB Configuration */ Reg gusbcfg; /* Core USB Configuration */ Reg grstctl; /* Core Reset */ Reg gintsts; /* Core Interrupt */ Reg gintmsk; /* Core Interrupt Mask */ Reg grxstsr; /* Receive Status Queue Read (RO) */ Reg grxstsp; /* Receive Status Queue Read & POP (RO) */ Reg grxfsiz; /* Receive FIFO Size */ Reg gnptxfsiz; /* Non Periodic Transmit FIFO Size */ Reg gnptxsts; /* Non Periodic Transmit FIFO/Queue Status (RO) */ Reg gi2cctl; /* I2C Access */ Reg gpvndctl; /* PHY Vendor Control */ Reg ggpio; /* General Purpose Input/Output */ Reg guid; /* User ID */ Reg gsnpsid; /* Synopsys ID (RO) */ Reg ghwcfg1; /* User HW Config1 (RO) (DEVICE) */ Reg ghwcfg2; /* User HW Config2 (RO) */ Reg ghwcfg3; /* User HW Config3 (RO) */ Reg ghwcfg4; /* User HW Config4 (RO)*/ Reg glpmcfg; /* Core LPM Configuration */ Reg gpwrdn; /* Global PowerDn */ Reg gdfifocfg; /* Global DFIFO SW Config (DEVICE?) */ Reg adpctl; /* ADP Control */ Reg reserved0[39]; Reg hptxfsiz; /* Host Periodic Transmit FIFO Size */ Reg dtxfsiz[15]; /* Device Periodic Transmit FIFOs (DEVICE) */ char pad0[0x400-0x140]; /* Host global registers 0x400-0x420 */ Reg hcfg; /* Configuration */ Reg hfir; /* Frame Interval */ Reg hfnum; /* Frame Number / Frame Remaining (RO) */ Reg reserved1; Reg hptxsts; /* Periodic Transmit FIFO / Queue Status */ Reg haint; /* All Channels Interrupt */ Reg haintmsk; /* All Channels Interrupt Mask */ Reg hflbaddr; /* Frame List Base Address */ char pad1[0x440-0x420]; /* Host port register 0x440 */ Reg hport0; /* Host Port 0 Control and Status */ char pad2[0x500-0x444]; /* Host channel specific registers 0x500-0x700 */ struct Hostchan { Reg hcchar; /* Characteristic */ Reg hcsplt; /* Split Control */ Reg hcint; /* Interrupt */ Reg hcintmsk; /* Interrupt Mask */ Reg hctsiz; /* Transfer Size */ Reg hcdma; /* DMA Address */ Reg reserved; Reg hcdmab; /* DMA Buffer Address */ } hchan[Maxchans]; char pad3[0xE00-0x700]; /* Power & clock gating control register 0xE00 */ Reg pcgcctl; }; enum { /* gotgctl */ Sesreqscs = 1<<0, Sesreq = 1<<1, Vbvalidoven = 1<<2, Vbvalidovval = 1<<3, Avalidoven = 1<<4, Avalidovval = 1<<5, Bvalidoven = 1<<6, Bvalidovval = 1<<7, Hstnegscs = 1<<8, Hnpreq = 1<<9, Hstsethnpen = 1<<10, Devhnpen = 1<<11, Conidsts = 1<<16, Dbnctime = 1<<17, Asesvld = 1<<18, Bsesvld = 1<<19, Otgver = 1<<20, Multvalidbc = 0x1F<<22, Chirpen = 1<<27, /* gotgint */ Sesenddet = 1<<2, Sesreqsucstschng= 1<<8, Hstnegsucstschng= 1<<9, Hstnegdet = 1<<17, Adevtoutchng = 1<<18, Debdone = 1<<19, Mvic = 1<<20, /* gahbcfg */ Glblintrmsk = 1<<0, /* bits 1:4 redefined for BCM2835 */ Axiburstlen = 0x3<<1, BURST1 = 3<<1, BURST2 = 2<<1, BURST3 = 1<<1, BURST4 = 0<<1, Axiwaitwrites = 1<<4, Dmaenable = 1<<5, Nptxfemplvl = 1<<7, NPTX_HALFEMPTY = 0<<7, NPTX_EMPTY = 1<<7, Ptxfemplvl = 1<<8, PTX_HALFEMPTY = 0<<8, PTX_EMPTY = 1<<8, Remmemsupp = 1<<21, Notialldmawrit = 1<<22, Ahbsingle = 1<<23, /* gusbcfg */ Toutcal = 0x7<<0, Phyif = 1<<3, Ulpi_utmi_sel = 1<<4, Fsintf = 1<<5, FsUnidir = 0<<5, FsBidir = 1<<5, Physel = 1<<6, PhyHighspeed = 0<<6, PhyFullspeed = 1<<6, Ddrsel = 1<<7, Srpcap = 1<<8, Hnpcap = 1<<9, Usbtrdtim = 0xf<<10, OUsbtrdtim = 10, Phylpwrclksel = 1<<15, Otgutmifssel = 1<<16, Ulpi_fsls = 1<<17, Ulpi_auto_res = 1<<18, Ulpi_clk_sus_m = 1<<19, Ulpi_ext_vbus_drv= 1<<20, Ulpi_int_vbus_indicator= 1<<21, Term_sel_dl_pulse= 1<<22, Indicator_complement= 1<<23, Indicator_pass_through= 1<<24, Ulpi_int_prot_dis= 1<<25, Ic_usb_cap = 1<<26, Ic_traffic_pull_remove= 1<<27, Tx_end_delay = 1<<28, Force_host_mode = 1<<29, Force_dev_mode = 1<<30, /* grstctl */ Csftrst = 1<<0, Hsftrst = 1<<1, Hstfrm = 1<<2, Intknqflsh = 1<<3, Rxfflsh = 1<<4, Txfflsh = 1<<5, Txfnum = 0x1f<<6, TXF_ALL = 0x10<<6, Dmareq = 1<<30, Ahbidle = 1<<31, /* gintsts, gintmsk */ Curmode = 1<<0, HOSTMODE = 1<<0, DEVMODE = 0<<0, Modemismatch = 1<<1, Otgintr = 1<<2, Sofintr = 1<<3, Rxstsqlvl = 1<<4, Nptxfempty = 1<<5, Ginnakeff = 1<<6, Goutnakeff = 1<<7, Ulpickint = 1<<8, I2cintr = 1<<9, Erlysuspend = 1<<10, Usbsuspend = 1<<11, Usbreset = 1<<12, Enumdone = 1<<13, Isooutdrop = 1<<14, Eopframe = 1<<15, Restoredone = 1<<16, Epmismatch = 1<<17, Inepintr = 1<<18, Outepintr = 1<<19, Incomplisoin = 1<<20, Incomplisoout = 1<<21, Fetsusp = 1<<22, Resetdet = 1<<23, Portintr = 1<<24, Hcintr = 1<<25, Ptxfempty = 1<<26, Lpmtranrcvd = 1<<27, Conidstschng = 1<<28, Disconnect = 1<<29, Sessreqintr = 1<<30, Wkupintr = 1<<31, /* grxsts[rp] */ Chnum = 0xf<<0, Bcnt = 0x7ff<<4, Dpid = 0x3<<15, Pktsts = 0xf<<17, PKTSTS_IN = 2<<17, PKTSTS_IN_XFER_COMP = 3<<17, PKTSTS_DATA_TOGGLE_ERR = 5<<17, PKTSTS_CH_HALTED = 7<<17, /* hptxfsiz, gnptxfsiz */ Startaddr = 0xffff<<0, Depth = 0xffff<<16, ODepth = 16, /* gnptxsts */ Nptxfspcavail = 0xffff<<0, Nptxqspcavail = 0xff<<16, Nptxqtop_terminate= 1<<24, Nptxqtop_token = 0x3<<25, Nptxqtop_chnep = 0xf<<27, /* gpvndctl */ Regdata = 0xff<<0, Vctrl = 0xff<<8, Regaddr16_21 = 0x3f<<16, Regwr = 1<<22, Newregreq = 1<<25, Vstsbsy = 1<<26, Vstsdone = 1<<27, Disulpidrvr = 1<<31, /* ggpio */ Gpi = 0xffff<<0, Gpo = 0xffff<<16, /* ghwcfg2 */ Op_mode = 0x7<<0, HNP_SRP_CAPABLE_OTG = 0<<0, SRP_ONLY_CAPABLE_OTG = 1<<0, NO_HNP_SRP_CAPABLE = 2<<0, SRP_CAPABLE_DEVICE = 3<<0, NO_SRP_CAPABLE_DEVICE = 4<<0, SRP_CAPABLE_HOST = 5<<0, NO_SRP_CAPABLE_HOST = 6<<0, Architecture = 0x3<<3, SLAVE_ONLY = 0<<3, EXT_DMA = 1<<3, INT_DMA = 2<<3, Point2point = 1<<5, Hs_phy_type = 0x3<<6, PHY_NOT_SUPPORTED = 0<<6, PHY_UTMI = 1<<6, PHY_ULPI = 2<<6, PHY_UTMI_ULPI = 3<<6, Fs_phy_type = 0x3<<8, Num_dev_ep = 0xf<<10, Num_host_chan = 0xf<<14, ONum_host_chan = 14, Perio_ep_supported= 1<<18, Dynamic_fifo = 1<<19, Nonperio_tx_q_depth= 0x3<<22, Host_perio_tx_q_depth= 0x3<<24, Dev_token_q_depth= 0x1f<<26, Otg_enable_ic_usb= 1<<31, /* ghwcfg3 */ Xfer_size_cntr_width = 0xf<<0, Packet_size_cntr_width = 0x7<<4, Otg_func = 1<<7, I2c = 1<<8, Vendor_ctrl_if = 1<<9, Optional_features = 1<<10, Synch_reset_type = 1<<11, Adp_supp = 1<<12, Otg_enable_hsic = 1<<13, Bc_support = 1<<14, Otg_lpm_en = 1<<15, Dfifo_depth = 0xffff<<16, ODfifo_depth = 16, /* ghwcfg4 */ Num_dev_perio_in_ep = 0xf<<0, Power_optimiz = 1<<4, Min_ahb_freq = 1<<5, Hiber = 1<<6, Xhiber = 1<<7, Utmi_phy_data_width = 0x3<<14, Num_dev_mode_ctrl_ep = 0xf<<16, Iddig_filt_en = 1<<20, Vbus_valid_filt_en = 1<<21, A_valid_filt_en = 1<<22, B_valid_filt_en = 1<<23, Session_end_filt_en = 1<<24, Ded_fifo_en = 1<<25, Num_in_eps = 0xf<<26, Desc_dma = 1<<30, Desc_dma_dyn = 1<<31, /* glpmcfg */ Lpm_cap_en = 1<<0, Appl_resp = 1<<1, Hird = 0xf<<2, Rem_wkup_en = 1<<6, En_utmi_sleep = 1<<7, Hird_thres = 0x1f<<8, Lpm_resp = 0x3<<13, Prt_sleep_sts = 1<<15, Sleep_state_resumeok= 1<<16, Lpm_chan_index = 0xf<<17, Retry_count = 0x7<<21, Send_lpm = 1<<24, Retry_count_sts = 0x7<<25, Hsic_connect = 1<<30, Inv_sel_hsic = 1<<31, /* gpwrdn */ Pmuintsel = 1<<0, Pmuactv = 1<<1, Restore = 1<<2, Pwrdnclmp = 1<<3, Pwrdnrstn = 1<<4, Pwrdnswtch = 1<<5, Dis_vbus = 1<<6, Lnstschng = 1<<7, Lnstchng_msk = 1<<8, Rst_det = 1<<9, Rst_det_msk = 1<<10, Disconn_det = 1<<11, Disconn_det_msk = 1<<12, Connect_det = 1<<13, Connect_det_msk = 1<<14, Srp_det = 1<<15, Srp_det_msk = 1<<16, Sts_chngint = 1<<17, Sts_chngint_msk = 1<<18, Linestate = 0x3<<19, Idsts = 1<<21, Bsessvld = 1<<22, Adp_int = 1<<23, Mult_val_id_bc = 0x1f<<24, /* gdfifocfg */ Gdfifocfg = 0xffff<<0, Epinfobase = 0xffff<<16, /* adpctl */ Prb_dschg = 0x3<<0, Prb_delta = 0x3<<2, Prb_per = 0x3<<4, Rtim = 0x7ff<<6, Enaprb = 1<<17, Enasns = 1<<18, Adpres = 1<<19, Adpen = 1<<20, Adp_prb_int = 1<<21, Adp_sns_int = 1<<22, Adp_tmout_int = 1<<23, Adp_prb_int_msk = 1<<24, Adp_sns_int_msk = 1<<25, Adp_tmout_int_msk= 1<<26, Ar = 0x3<<27, /* hcfg */ Fslspclksel = 0x3<<0, HCFG_30_60_MHZ = 0<<0, HCFG_48_MHZ = 1<<0, HCFG_6_MHZ = 2<<0, Fslssupp = 1<<2, Ena32khzs = 1<<7, Resvalid = 0xff<<8, Descdma = 1<<23, Frlisten = 0x3<<24, Modechtimen = 1<<31, /* hfir */ Frint = 0xffff<<0, Hfirrldctrl = 1<<16, /* hfnum */ Frnum = 0xffff<<0, MAX_FRNUM = 0x3FFF<<0, Frrem = 0xffff<<16, /* hptxsts */ Ptxfspcavail = 0xffff<<0, Ptxqspcavail = 0xff<<16, Ptxqtop_terminate= 1<<24, Ptxqtop_token = 0x3<<25, Ptxqtop_chnum = 0xf<<27, Ptxqtop_odd = 1<<31, /* haint, haintmsk */ #define CHANINT(n) (1<<(n)) /* hport0 */ Prtconnsts = 1<<0, /* connect status (RO) */ Prtconndet = 1<<1, /* connect detected R/W1C) */ Prtena = 1<<2, /* enable (R/W1C) */ Prtenchng = 1<<3, /* enable/disable change (R/W1C) */ Prtovrcurract = 1<<4, /* overcurrent active (RO) */ Prtovrcurrchng = 1<<5, /* overcurrent change (R/W1C) */ Prtres = 1<<6, /* resume */ Prtsusp = 1<<7, /* suspend */ Prtrst = 1<<8, /* reset */ Prtlnsts = 0x3<<10, /* line state {D+,D-} (RO) */ Prtpwr = 1<<12, /* power on */ Prttstctl = 0xf<<13, /* test */ Prtspd = 0x3<<17, /* speed (RO) */ HIGHSPEED = 0<<17, FULLSPEED = 1<<17, LOWSPEED = 2<<17, /* hcchar */ Mps = 0x7ff<<0, /* endpoint maximum packet size */ Epnum = 0xf<<11, /* endpoint number */ OEpnum = 11, Epdir = 1<<15, /* endpoint direction */ Epout = 0<<15, Epin = 1<<15, Lspddev = 1<<17, /* device is lowspeed */ Eptype = 0x3<<18, /* endpoint type */ Epctl = 0<<18, Episo = 1<<18, Epbulk = 2<<18, Epintr = 3<<18, Multicnt = 0x3<<20, /* transactions per μframe */ /* or retries per periodic split */ OMulticnt = 20, Devaddr = 0x7f<<22, /* device address */ ODevaddr = 22, Oddfrm = 1<<29, /* xfer in odd frame (iso/interrupt) */ Chdis = 1<<30, /* channel disable (write 1 only) */ Chen = 1<<31, /* channel enable (write 1 only) */ /* hcsplt */ Prtaddr = 0x7f<<0, /* port address of recipient */ /* transaction translator */ Hubaddr = 0x7f<<7, /* dev address of transaction */ /* translator's hub */ OHubaddr = 7, Xactpos = 0x3<<14, /* payload's position within transaction */ POS_MID = 0<<14, POS_END = 1<<14, POS_BEGIN = 2<<14, POS_ALL = 3<<14, /* all of data (<= 188 bytes) */ Compsplt = 1<<16, /* do complete split */ Spltena = 1<<31, /* channel enabled to do splits */ /* hcint, hcintmsk */ Xfercomp = 1<<0, /* transfer completed without error */ Chhltd = 1<<1, /* channel halted */ Ahberr = 1<<2, /* AHB dma error */ Stall = 1<<3, Nak = 1<<4, Ack = 1<<5, Nyet = 1<<6, Xacterr = 1<<7, /* transaction error (crc, t/o, bit stuff, eop) */ Bblerr = 1<<8, Frmovrun = 1<<9, Datatglerr = 1<<10, Bna = 1<<11, Xcs_xact = 1<<12, Frm_list_roll = 1<<13, /* hctsiz */ Xfersize = 0x7ffff<<0, /* expected total bytes */ Pktcnt = 0x3ff<<19, /* expected number of packets */ OPktcnt = 19, Pid = 0x3<<29, /* packet id for initial transaction */ DATA0 = 0<<29, DATA1 = 2<<29, /* sic */ DATA2 = 1<<29, /* sic */ MDATA = 3<<29, /* (non-ctl ep) */ SETUP = 3<<29, /* (ctl ep) */ Dopng = 1<<31, /* do PING protocol */ /* pcgcctl */ Stoppclk = 1<<0, Gatehclk = 1<<1, Pwrclmp = 1<<2, Rstpdwnmodule = 1<<3, Enbl_sleep_gating = 1<<5, Phy_in_sleep = 1<<6, Deep_sleep = 1<<7, Resetaftsusp = 1<<8, Restoremode = 1<<9, Enbl_extnd_hiber = 1<<10, Extnd_hiber_pwrclmp = 1<<11, Extnd_hiber_switch = 1<<12, Ess_reg_restored = 1<<13, Prt_clk_sel = 0x3<<14, Port_power = 1<<16, Max_xcvrselect = 0x3<<17, Max_termsel = 1<<19, Mac_dev_addr = 0x7f<<20, P2hd_dev_enum_spd = 0x3<<27, P2hd_prt_spd = 0x3<<29, If_dev_mode = 1<<31, };