1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * Copyright (C) 2011 Marvell International Ltd. All rights reserved. 4*4882a593Smuzhiyun */ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun #ifndef __MV_U3D_H 7*4882a593Smuzhiyun #define __MV_U3D_H 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #define MV_U3D_EP_CONTEXT_ALIGNMENT 32 10*4882a593Smuzhiyun #define MV_U3D_TRB_ALIGNMENT 16 11*4882a593Smuzhiyun #define MV_U3D_DMA_BOUNDARY 4096 12*4882a593Smuzhiyun #define MV_U3D_EP0_MAX_PKT_SIZE 512 13*4882a593Smuzhiyun 14*4882a593Smuzhiyun /* ep0 transfer state */ 15*4882a593Smuzhiyun #define MV_U3D_WAIT_FOR_SETUP 0 16*4882a593Smuzhiyun #define MV_U3D_DATA_STATE_XMIT 1 17*4882a593Smuzhiyun #define MV_U3D_DATA_STATE_NEED_ZLP 2 18*4882a593Smuzhiyun #define MV_U3D_WAIT_FOR_OUT_STATUS 3 19*4882a593Smuzhiyun #define MV_U3D_DATA_STATE_RECV 4 20*4882a593Smuzhiyun #define MV_U3D_STATUS_STAGE 5 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun #define MV_U3D_EP_MAX_LENGTH_TRANSFER 0x10000 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun /* USB3 Interrupt Status */ 25*4882a593Smuzhiyun #define MV_U3D_USBINT_SETUP 0x00000001 26*4882a593Smuzhiyun #define MV_U3D_USBINT_RX_COMPLETE 0x00000002 27*4882a593Smuzhiyun #define MV_U3D_USBINT_TX_COMPLETE 0x00000004 28*4882a593Smuzhiyun #define MV_U3D_USBINT_UNDER_RUN 0x00000008 29*4882a593Smuzhiyun #define MV_U3D_USBINT_RXDESC_ERR 0x00000010 30*4882a593Smuzhiyun #define MV_U3D_USBINT_TXDESC_ERR 0x00000020 31*4882a593Smuzhiyun #define MV_U3D_USBINT_RX_TRB_COMPLETE 0x00000040 32*4882a593Smuzhiyun #define MV_U3D_USBINT_TX_TRB_COMPLETE 0x00000080 33*4882a593Smuzhiyun #define MV_U3D_USBINT_VBUS_VALID 0x00010000 34*4882a593Smuzhiyun #define MV_U3D_USBINT_STORAGE_CMD_FULL 0x00020000 35*4882a593Smuzhiyun #define MV_U3D_USBINT_LINK_CHG 0x01000000 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun /* USB3 Interrupt Enable */ 38*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_SETUP 0x00000001 39*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_RX_COMPLETE 0x00000002 40*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_TX_COMPLETE 0x00000004 41*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_UNDER_RUN 0x00000008 42*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_RXDESC_ERR 0x00000010 43*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_TXDESC_ERR 0x00000020 44*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_RX_TRB_COMPLETE 0x00000040 45*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_TX_TRB_COMPLETE 0x00000080 46*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_RX_BUFFER_ERR 0x00000100 47*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_VBUS_VALID 0x00010000 48*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_STORAGE_CMD_FULL 0x00020000 49*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_LINK_CHG 0x01000000 50*4882a593Smuzhiyun #define MV_U3D_INTR_ENABLE_PRIME_STATUS 0x02000000 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* USB3 Link Change */ 53*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_LINK_UP 0x00000001 54*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_SUSPEND 0x00000002 55*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_RESUME 0x00000004 56*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_WRESET 0x00000008 57*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_HRESET 0x00000010 58*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_VBUS_INVALID 0x00000020 59*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_INACT 0x00000040 60*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_DISABLE_AFTER_U0 0x00000080 61*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_U1 0x00000100 62*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_U2 0x00000200 63*4882a593Smuzhiyun #define MV_U3D_LINK_CHANGE_U3 0x00000400 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun /* bridge setting */ 66*4882a593Smuzhiyun #define MV_U3D_BRIDGE_SETTING_VBUS_VALID (1 << 16) 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun /* Command Register Bit Masks */ 69*4882a593Smuzhiyun #define MV_U3D_CMD_RUN_STOP 0x00000001 70*4882a593Smuzhiyun #define MV_U3D_CMD_CTRL_RESET 0x00000002 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun /* ep control register */ 73*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_TYPE_CONTROL 0 74*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_TYPE_ISOC 1 75*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_TYPE_BULK 2 76*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_TYPE_INT 3 77*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_ENABLE_SHIFT 4 78*4882a593Smuzhiyun #define MV_U3D_EPXCR_MAX_BURST_SIZE_SHIFT 12 79*4882a593Smuzhiyun #define MV_U3D_EPXCR_MAX_PACKET_SIZE_SHIFT 16 80*4882a593Smuzhiyun #define MV_U3D_USB_BULK_BURST_OUT 6 81*4882a593Smuzhiyun #define MV_U3D_USB_BULK_BURST_IN 14 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_FLUSH (1 << 7) 84*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_HALT (1 << 1) 85*4882a593Smuzhiyun #define MV_U3D_EPXCR_EP_INIT (1) 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun /* TX/RX Status Register */ 88*4882a593Smuzhiyun #define MV_U3D_XFERSTATUS_COMPLETE_SHIFT 24 89*4882a593Smuzhiyun #define MV_U3D_COMPLETE_INVALID 0 90*4882a593Smuzhiyun #define MV_U3D_COMPLETE_SUCCESS 1 91*4882a593Smuzhiyun #define MV_U3D_COMPLETE_BUFF_ERR 2 92*4882a593Smuzhiyun #define MV_U3D_COMPLETE_SHORT_PACKET 3 93*4882a593Smuzhiyun #define MV_U3D_COMPLETE_TRB_ERR 5 94*4882a593Smuzhiyun #define MV_U3D_XFERSTATUS_TRB_LENGTH_MASK (0xFFFFFF) 95*4882a593Smuzhiyun 96*4882a593Smuzhiyun #define MV_U3D_USB_LINK_BYPASS_VBUS 0x8 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun #define MV_U3D_LTSSM_PHY_INIT_DONE 0x80000000 99*4882a593Smuzhiyun #define MV_U3D_LTSSM_NEVER_GO_COMPLIANCE 0x40000000 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun #define MV_U3D_USB3_OP_REGS_OFFSET 0x100 102*4882a593Smuzhiyun #define MV_U3D_USB3_PHY_OFFSET 0xB800 103*4882a593Smuzhiyun 104*4882a593Smuzhiyun #define DCS_ENABLE 0x1 105*4882a593Smuzhiyun 106*4882a593Smuzhiyun /* timeout */ 107*4882a593Smuzhiyun #define MV_U3D_RESET_TIMEOUT 10000 108*4882a593Smuzhiyun #define MV_U3D_FLUSH_TIMEOUT 100000 109*4882a593Smuzhiyun #define MV_U3D_OWN_TIMEOUT 10000 110*4882a593Smuzhiyun #define LOOPS_USEC_SHIFT 4 111*4882a593Smuzhiyun #define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) 112*4882a593Smuzhiyun #define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT) 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun /* ep direction */ 115*4882a593Smuzhiyun #define MV_U3D_EP_DIR_IN 1 116*4882a593Smuzhiyun #define MV_U3D_EP_DIR_OUT 0 117*4882a593Smuzhiyun #define mv_u3d_ep_dir(ep) (((ep)->ep_num == 0) ? \ 118*4882a593Smuzhiyun ((ep)->u3d->ep0_dir) : ((ep)->direction)) 119*4882a593Smuzhiyun 120*4882a593Smuzhiyun /* usb capability registers */ 121*4882a593Smuzhiyun struct mv_u3d_cap_regs { 122*4882a593Smuzhiyun u32 rsvd[5]; 123*4882a593Smuzhiyun u32 dboff; /* doorbell register offset */ 124*4882a593Smuzhiyun u32 rtsoff; /* runtime register offset */ 125*4882a593Smuzhiyun u32 vuoff; /* vendor unique register offset */ 126*4882a593Smuzhiyun }; 127*4882a593Smuzhiyun 128*4882a593Smuzhiyun /* operation registers */ 129*4882a593Smuzhiyun struct mv_u3d_op_regs { 130*4882a593Smuzhiyun u32 usbcmd; /* Command register */ 131*4882a593Smuzhiyun u32 rsvd1[11]; 132*4882a593Smuzhiyun u32 dcbaapl; /* Device Context Base Address low register */ 133*4882a593Smuzhiyun u32 dcbaaph; /* Device Context Base Address high register */ 134*4882a593Smuzhiyun u32 rsvd2[243]; 135*4882a593Smuzhiyun u32 portsc; /* port status and control register*/ 136*4882a593Smuzhiyun u32 portlinkinfo; /* port link info register*/ 137*4882a593Smuzhiyun u32 rsvd3[9917]; 138*4882a593Smuzhiyun u32 doorbell; /* doorbell register */ 139*4882a593Smuzhiyun }; 140*4882a593Smuzhiyun 141*4882a593Smuzhiyun /* control endpoint enable registers */ 142*4882a593Smuzhiyun struct epxcr { 143*4882a593Smuzhiyun u32 epxoutcr0; /* ep out control 0 register */ 144*4882a593Smuzhiyun u32 epxoutcr1; /* ep out control 1 register */ 145*4882a593Smuzhiyun u32 epxincr0; /* ep in control 0 register */ 146*4882a593Smuzhiyun u32 epxincr1; /* ep in control 1 register */ 147*4882a593Smuzhiyun }; 148*4882a593Smuzhiyun 149*4882a593Smuzhiyun /* transfer status registers */ 150*4882a593Smuzhiyun struct xferstatus { 151*4882a593Smuzhiyun u32 curdeqlo; /* current TRB pointer low */ 152*4882a593Smuzhiyun u32 curdeqhi; /* current TRB pointer high */ 153*4882a593Smuzhiyun u32 statuslo; /* transfer status low */ 154*4882a593Smuzhiyun u32 statushi; /* transfer status high */ 155*4882a593Smuzhiyun }; 156*4882a593Smuzhiyun 157*4882a593Smuzhiyun /* vendor unique control registers */ 158*4882a593Smuzhiyun struct mv_u3d_vuc_regs { 159*4882a593Smuzhiyun u32 ctrlepenable; /* control endpoint enable register */ 160*4882a593Smuzhiyun u32 setuplock; /* setup lock register */ 161*4882a593Smuzhiyun u32 endcomplete; /* endpoint transfer complete register */ 162*4882a593Smuzhiyun u32 intrcause; /* interrupt cause register */ 163*4882a593Smuzhiyun u32 intrenable; /* interrupt enable register */ 164*4882a593Smuzhiyun u32 trbcomplete; /* TRB complete register */ 165*4882a593Smuzhiyun u32 linkchange; /* link change register */ 166*4882a593Smuzhiyun u32 rsvd1[5]; 167*4882a593Smuzhiyun u32 trbunderrun; /* TRB underrun register */ 168*4882a593Smuzhiyun u32 rsvd2[43]; 169*4882a593Smuzhiyun u32 bridgesetting; /* bridge setting register */ 170*4882a593Smuzhiyun u32 rsvd3[7]; 171*4882a593Smuzhiyun struct xferstatus txst[16]; /* TX status register */ 172*4882a593Smuzhiyun struct xferstatus rxst[16]; /* RX status register */ 173*4882a593Smuzhiyun u32 ltssm; /* LTSSM control register */ 174*4882a593Smuzhiyun u32 pipe; /* PIPE control register */ 175*4882a593Smuzhiyun u32 linkcr0; /* link control 0 register */ 176*4882a593Smuzhiyun u32 linkcr1; /* link control 1 register */ 177*4882a593Smuzhiyun u32 rsvd6[60]; 178*4882a593Smuzhiyun u32 mib0; /* MIB0 counter register */ 179*4882a593Smuzhiyun u32 usblink; /* usb link control register */ 180*4882a593Smuzhiyun u32 ltssmstate; /* LTSSM state register */ 181*4882a593Smuzhiyun u32 linkerrorcause; /* link error cause register */ 182*4882a593Smuzhiyun u32 rsvd7[60]; 183*4882a593Smuzhiyun u32 devaddrtiebrkr; /* device address and tie breaker */ 184*4882a593Smuzhiyun u32 itpinfo0; /* ITP info 0 register */ 185*4882a593Smuzhiyun u32 itpinfo1; /* ITP info 1 register */ 186*4882a593Smuzhiyun u32 rsvd8[61]; 187*4882a593Smuzhiyun struct epxcr epcr[16]; /* ep control register */ 188*4882a593Smuzhiyun u32 rsvd9[64]; 189*4882a593Smuzhiyun u32 phyaddr; /* PHY address register */ 190*4882a593Smuzhiyun u32 phydata; /* PHY data register */ 191*4882a593Smuzhiyun }; 192*4882a593Smuzhiyun 193*4882a593Smuzhiyun /* Endpoint context structure */ 194*4882a593Smuzhiyun struct mv_u3d_ep_context { 195*4882a593Smuzhiyun u32 rsvd0; 196*4882a593Smuzhiyun u32 rsvd1; 197*4882a593Smuzhiyun u32 trb_addr_lo; /* TRB address low 32 bit */ 198*4882a593Smuzhiyun u32 trb_addr_hi; /* TRB address high 32 bit */ 199*4882a593Smuzhiyun u32 rsvd2; 200*4882a593Smuzhiyun u32 rsvd3; 201*4882a593Smuzhiyun struct usb_ctrlrequest setup_buffer; /* setup data buffer */ 202*4882a593Smuzhiyun }; 203*4882a593Smuzhiyun 204*4882a593Smuzhiyun /* TRB control data structure */ 205*4882a593Smuzhiyun struct mv_u3d_trb_ctrl { 206*4882a593Smuzhiyun u32 own:1; /* owner of TRB */ 207*4882a593Smuzhiyun u32 rsvd1:3; 208*4882a593Smuzhiyun u32 chain:1; /* associate this TRB with the 209*4882a593Smuzhiyun next TRB on the Ring */ 210*4882a593Smuzhiyun u32 ioc:1; /* interrupt on complete */ 211*4882a593Smuzhiyun u32 rsvd2:4; 212*4882a593Smuzhiyun u32 type:6; /* TRB type */ 213*4882a593Smuzhiyun #define TYPE_NORMAL 1 214*4882a593Smuzhiyun #define TYPE_DATA 3 215*4882a593Smuzhiyun #define TYPE_LINK 6 216*4882a593Smuzhiyun u32 dir:1; /* Working at data stage of control endpoint 217*4882a593Smuzhiyun operation. 0 is OUT and 1 is IN. */ 218*4882a593Smuzhiyun u32 rsvd3:15; 219*4882a593Smuzhiyun }; 220*4882a593Smuzhiyun 221*4882a593Smuzhiyun /* TRB data structure 222*4882a593Smuzhiyun * For multiple TRB, all the TRBs' physical address should be continuous. 223*4882a593Smuzhiyun */ 224*4882a593Smuzhiyun struct mv_u3d_trb_hw { 225*4882a593Smuzhiyun u32 buf_addr_lo; /* data buffer address low 32 bit */ 226*4882a593Smuzhiyun u32 buf_addr_hi; /* data buffer address high 32 bit */ 227*4882a593Smuzhiyun u32 trb_len; /* transfer length */ 228*4882a593Smuzhiyun struct mv_u3d_trb_ctrl ctrl; /* TRB control data */ 229*4882a593Smuzhiyun }; 230*4882a593Smuzhiyun 231*4882a593Smuzhiyun /* TRB structure */ 232*4882a593Smuzhiyun struct mv_u3d_trb { 233*4882a593Smuzhiyun struct mv_u3d_trb_hw *trb_hw; /* point to the trb_hw structure */ 234*4882a593Smuzhiyun dma_addr_t trb_dma; /* dma address for this trb_hw */ 235*4882a593Smuzhiyun struct list_head trb_list; /* trb list */ 236*4882a593Smuzhiyun }; 237*4882a593Smuzhiyun 238*4882a593Smuzhiyun /* device data structure */ 239*4882a593Smuzhiyun struct mv_u3d { 240*4882a593Smuzhiyun struct usb_gadget gadget; 241*4882a593Smuzhiyun struct usb_gadget_driver *driver; 242*4882a593Smuzhiyun spinlock_t lock; /* device lock */ 243*4882a593Smuzhiyun struct completion *done; 244*4882a593Smuzhiyun struct device *dev; 245*4882a593Smuzhiyun int irq; 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun /* usb controller registers */ 248*4882a593Smuzhiyun struct mv_u3d_cap_regs __iomem *cap_regs; 249*4882a593Smuzhiyun struct mv_u3d_op_regs __iomem *op_regs; 250*4882a593Smuzhiyun struct mv_u3d_vuc_regs __iomem *vuc_regs; 251*4882a593Smuzhiyun void __iomem *phy_regs; 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun unsigned int max_eps; 254*4882a593Smuzhiyun struct mv_u3d_ep_context *ep_context; 255*4882a593Smuzhiyun size_t ep_context_size; 256*4882a593Smuzhiyun dma_addr_t ep_context_dma; 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun struct dma_pool *trb_pool; /* for TRB data structure */ 259*4882a593Smuzhiyun struct mv_u3d_ep *eps; 260*4882a593Smuzhiyun 261*4882a593Smuzhiyun struct mv_u3d_req *status_req; /* ep0 status request */ 262*4882a593Smuzhiyun struct usb_ctrlrequest local_setup_buff; /* store setup data*/ 263*4882a593Smuzhiyun 264*4882a593Smuzhiyun unsigned int resume_state; /* USB state to resume */ 265*4882a593Smuzhiyun unsigned int usb_state; /* USB current state */ 266*4882a593Smuzhiyun unsigned int ep0_state; /* Endpoint zero state */ 267*4882a593Smuzhiyun unsigned int ep0_dir; 268*4882a593Smuzhiyun 269*4882a593Smuzhiyun unsigned int dev_addr; /* device address */ 270*4882a593Smuzhiyun 271*4882a593Smuzhiyun unsigned int errors; 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun unsigned softconnect:1; 274*4882a593Smuzhiyun unsigned vbus_active:1; /* vbus is active or not */ 275*4882a593Smuzhiyun unsigned remote_wakeup:1; /* support remote wakeup */ 276*4882a593Smuzhiyun unsigned clock_gating:1; /* clock gating or not */ 277*4882a593Smuzhiyun unsigned active:1; /* udc is active or not */ 278*4882a593Smuzhiyun unsigned vbus_valid_detect:1; /* udc vbus detection */ 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun struct mv_usb_addon_irq *vbus; 281*4882a593Smuzhiyun unsigned int power; 282*4882a593Smuzhiyun 283*4882a593Smuzhiyun struct clk *clk; 284*4882a593Smuzhiyun }; 285*4882a593Smuzhiyun 286*4882a593Smuzhiyun /* endpoint data structure */ 287*4882a593Smuzhiyun struct mv_u3d_ep { 288*4882a593Smuzhiyun struct usb_ep ep; 289*4882a593Smuzhiyun struct mv_u3d *u3d; 290*4882a593Smuzhiyun struct list_head queue; /* ep request queued hardware */ 291*4882a593Smuzhiyun struct list_head req_list; /* list of ep request */ 292*4882a593Smuzhiyun struct mv_u3d_ep_context *ep_context; /* ep context */ 293*4882a593Smuzhiyun u32 direction; 294*4882a593Smuzhiyun char name[14]; 295*4882a593Smuzhiyun u32 processing; /* there is ep request 296*4882a593Smuzhiyun queued on haredware */ 297*4882a593Smuzhiyun spinlock_t req_lock; /* ep lock */ 298*4882a593Smuzhiyun unsigned wedge:1; 299*4882a593Smuzhiyun unsigned enabled:1; 300*4882a593Smuzhiyun unsigned ep_type:2; 301*4882a593Smuzhiyun unsigned ep_num:8; 302*4882a593Smuzhiyun }; 303*4882a593Smuzhiyun 304*4882a593Smuzhiyun /* request data structure */ 305*4882a593Smuzhiyun struct mv_u3d_req { 306*4882a593Smuzhiyun struct usb_request req; 307*4882a593Smuzhiyun struct mv_u3d_ep *ep; 308*4882a593Smuzhiyun struct list_head queue; /* ep requst queued on hardware */ 309*4882a593Smuzhiyun struct list_head list; /* ep request list */ 310*4882a593Smuzhiyun struct list_head trb_list; /* trb list of a request */ 311*4882a593Smuzhiyun 312*4882a593Smuzhiyun struct mv_u3d_trb *trb_head; /* point to first trb of a request */ 313*4882a593Smuzhiyun unsigned trb_count; /* TRB number in the chain */ 314*4882a593Smuzhiyun unsigned chain; /* TRB chain or not */ 315*4882a593Smuzhiyun }; 316*4882a593Smuzhiyun 317*4882a593Smuzhiyun #endif 318