510 lines
12 KiB
C
510 lines
12 KiB
C
/*
|
|
* 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,
|
|
};
|