Patrick Georgi | 6615ef3 | 2010-08-13 09:18:58 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * This file is part of the libpayload project. |
| 3 | * |
| 4 | * Copyright (C) 2010 Patrick Georgi |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * 3. The name of the author may not be used to endorse or promote products |
| 15 | * derived from this software without specific prior written permission. |
| 16 | * |
| 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
| 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
| 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
| 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| 27 | * SUCH DAMAGE. |
| 28 | */ |
| 29 | |
| 30 | #ifndef __XHCI_PRIVATE_H |
| 31 | #define __XHCI_PRIVATE_H |
| 32 | |
| 33 | #include <usb/usb.h> |
| 34 | |
| 35 | #define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) |
| 36 | |
| 37 | typedef volatile union trb { |
| 38 | // transfer |
| 39 | |
| 40 | // events |
| 41 | #define TRB_EV_CMD_CMPL 33 |
| 42 | struct { |
| 43 | u32 Cmd_TRB_Pointer_lo; |
| 44 | u32 Cmd_TRB_Pointer_hi; |
| 45 | struct { |
| 46 | unsigned long:24; |
| 47 | unsigned long Completion_Code:8; |
| 48 | } __attribute__ ((packed)); |
| 49 | struct { |
| 50 | unsigned long C:1; |
| 51 | unsigned long:9; |
| 52 | unsigned long TRB_Type:6; |
| 53 | unsigned long VF_ID:8; |
| 54 | unsigned long Slot_ID:8; |
| 55 | } __attribute__ ((packed)); |
| 56 | } __attribute__ ((packed)) event_cmd_cmpl; |
| 57 | |
| 58 | #define TRB_EV_PORTSC 34 |
| 59 | struct { |
| 60 | struct { |
| 61 | unsigned long:24; |
| 62 | unsigned long Port:8; |
| 63 | } __attribute__ ((packed)); |
| 64 | u32 rsvd; |
| 65 | struct { |
| 66 | unsigned long:24; |
| 67 | unsigned long Completion_Code:8; |
| 68 | } __attribute__ ((packed)); |
| 69 | struct { |
| 70 | unsigned long C:1; |
| 71 | unsigned long:9; |
| 72 | unsigned long TRB_Type:6; |
| 73 | unsigned long:16; |
| 74 | } __attribute__ ((packed)); |
| 75 | } __attribute__ ((packed)) event_portsc; |
| 76 | |
| 77 | // commands |
| 78 | #define TRB_CMD_NOOP 23 |
| 79 | struct { |
| 80 | u32 rsvd[3]; |
| 81 | struct { |
| 82 | unsigned long C:1; |
| 83 | unsigned long:9; |
| 84 | unsigned long TRB_Type:6; |
| 85 | unsigned long:16; |
| 86 | } __attribute__ ((packed)); |
| 87 | } __attribute__ ((packed)) cmd_No_Op; |
| 88 | |
| 89 | // "others" |
| 90 | struct { |
| 91 | u32 Ring_Segment_Ptr_lo; |
| 92 | u32 Ring_Segment_Ptr_hi; |
| 93 | struct { |
| 94 | unsigned long:22; |
| 95 | unsigned long Interrupter_Target; |
| 96 | } __attribute__ ((packed)); |
| 97 | struct { |
| 98 | unsigned long C:1; |
| 99 | unsigned long TC:1; |
| 100 | unsigned long:2; |
| 101 | unsigned long CH:1; |
| 102 | unsigned long IOC:1; |
| 103 | unsigned long:4; |
| 104 | unsigned long TRB_Type:6; |
| 105 | unsigned long:16; |
| 106 | } __attribute__ ((packed)); |
| 107 | } __attribute__ ((packed)) link; |
| 108 | } trb_t; |
| 109 | |
| 110 | typedef struct slotctx { |
| 111 | struct { |
| 112 | unsigned long Route_String:20; |
| 113 | unsigned long Speed:4; |
| 114 | unsigned long:1; |
| 115 | unsigned long MTT:1; |
| 116 | unsigned long Hub:1; |
| 117 | unsigned long Context_Entries:5; |
| 118 | } __attribute__ ((packed)); |
| 119 | struct { |
| 120 | unsigned long Max_Exit_Latency:16; |
| 121 | unsigned long Root_Hub_Port_Number:8; |
| 122 | unsigned long Number_of_Ports:8; |
| 123 | } __attribute__ ((packed)); |
| 124 | struct { |
| 125 | unsigned long TT_Hub_Slot_ID:8; |
| 126 | unsigned long TT_Port_Number:8; |
| 127 | unsigned long TTT:2; |
| 128 | unsigned long:4; |
| 129 | unsigned long Interrupter_Target:10; |
| 130 | } __attribute__ ((packed)); |
| 131 | struct { |
| 132 | unsigned long USB_Device_Address:8; |
| 133 | unsigned long:19; |
| 134 | unsigned long Slot_State:5; |
| 135 | } __attribute__ ((packed)); |
| 136 | u32 rsvd[4]; |
| 137 | } slotctx_t; |
| 138 | |
| 139 | typedef struct epctx { |
| 140 | struct { |
| 141 | unsigned long EP_State:3; |
| 142 | unsigned long:5; |
| 143 | unsigned long Mult:2; |
| 144 | unsigned long MaxPStreams:5; |
| 145 | unsigned long LSA:1; |
| 146 | unsigned long Interval:8; |
| 147 | unsigned long:8; |
| 148 | } __attribute__ ((packed)); |
| 149 | struct { |
| 150 | unsigned long:1; |
| 151 | unsigned long CErr:2; |
| 152 | unsigned long EP_Type:3; |
| 153 | unsigned long:1; |
| 154 | unsigned long HID:1; |
| 155 | unsigned long Max_Burst_Size:8; |
| 156 | unsigned long Max_Packet_Size:16; |
| 157 | } __attribute__ ((packed)); |
| 158 | union { |
| 159 | u32 TR_Dequeue_Pointer_lo; |
| 160 | struct { |
| 161 | unsigned long DCS:1; |
| 162 | unsigned long:3; |
| 163 | } __attribute__ ((packed)); |
| 164 | } __attribute__ ((packed)); |
| 165 | u32 TR_Dequeue_Pointer_hi; |
| 166 | struct { |
| 167 | unsigned long Average_TRB_Length:16; |
| 168 | unsigned long Max_ESIT_Payload:16; |
| 169 | } __attribute__ ((packed)); |
| 170 | u32 rsvd[3]; |
| 171 | } epctx_t; |
| 172 | |
| 173 | typedef struct devctx { |
| 174 | slotctx_t slot; |
| 175 | epctx_t ep0; |
| 176 | struct { |
| 177 | epctx_t out; |
| 178 | epctx_t in; |
| 179 | } eps[15]; |
| 180 | } devctx_t; |
| 181 | |
| 182 | typedef struct devctxp { |
| 183 | devctx_t *ptr; |
| 184 | void *upper; |
| 185 | } devctxp_t; |
| 186 | |
| 187 | typedef struct erst_entry { |
| 188 | u32 seg_base_lo; |
| 189 | u32 seg_base_hi; |
| 190 | u32 seg_size; |
| 191 | u32 rsvd; |
| 192 | } erst_entry_t; |
| 193 | |
| 194 | typedef struct xhci { |
| 195 | /* capreg is read-only, so no need for volatile, |
| 196 | and thus 32bit accesses can be assumed. */ |
| 197 | struct capreg { |
| 198 | u8 caplength; |
| 199 | u8 res1; |
| 200 | union { |
| 201 | u16 hciversion; |
| 202 | struct { |
| 203 | u8 hciver_lo; |
| 204 | u8 hciver_hi; |
| 205 | } __attribute__ ((packed)); |
| 206 | } __attribute__ ((packed)); |
| 207 | union { |
| 208 | u32 hcsparams1; |
| 209 | struct { |
| 210 | unsigned long MaxSlots:7; |
| 211 | unsigned long MaxIntrs:11; |
| 212 | unsigned long:6; |
| 213 | unsigned long MaxPorts:8; |
| 214 | } __attribute__ ((packed)); |
| 215 | } __attribute__ ((packed)); |
| 216 | union { |
| 217 | u32 hcsparams2; |
| 218 | struct { |
| 219 | unsigned long IST:4; |
| 220 | unsigned long ERST_Max:4; |
| 221 | unsigned long:18; |
| 222 | unsigned long SPR:1; |
| 223 | unsigned long Max_Scratchpad_Bufs:5; |
| 224 | } __attribute__ ((packed)); |
| 225 | } __attribute__ ((packed)); |
| 226 | union { |
| 227 | u32 hcsparams3; |
| 228 | struct { |
| 229 | unsigned long u1latency:8; |
| 230 | unsigned long:8; |
| 231 | unsigned long u2latency:16; |
| 232 | } __attribute__ ((packed)); |
| 233 | } __attribute__ ((packed)); |
| 234 | union { |
| 235 | u32 hccparams; |
| 236 | struct { |
| 237 | unsigned long ac64:1; |
| 238 | unsigned long bnc:1; |
| 239 | unsigned long csz:1; |
| 240 | unsigned long ppc:1; |
| 241 | unsigned long pind:1; |
| 242 | unsigned long lhrc:1; |
| 243 | unsigned long ltc:1; |
| 244 | unsigned long nss:1; |
| 245 | unsigned long:4; |
| 246 | unsigned long MaxPSASize:4; |
| 247 | unsigned long xECP:16; |
| 248 | } __attribute__ ((packed)); |
| 249 | } __attribute__ ((packed)); |
| 250 | u32 dboff; |
| 251 | u32 rtsoff; |
| 252 | } __attribute__ ((packed)) *capreg; |
| 253 | |
| 254 | /* opreg is R/W is most places, so volatile access is necessary. |
| 255 | volatile means that the compiler seeks byte writes if possible, |
| 256 | making bitfields unusable for MMIO register blocks. Yay C :-( */ |
| 257 | volatile struct opreg { |
| 258 | u32 usbcmd; |
| 259 | #define USBCMD_RS 1<<0 |
| 260 | #define USBCMD_HCRST 1<<1 |
| 261 | u32 usbsts; |
| 262 | #define USBSTS_HCH 1<<0 |
| 263 | #define USBSTS_HSE 1<<2 |
| 264 | #define USBSTS_EINT 1<<3 |
| 265 | #define USBSTS_PCD 1<<4 |
| 266 | #define USBSTS_CNR 1<<11 |
| 267 | u32 pagesize; |
| 268 | u8 res1[0x13-0x0c+1]; |
| 269 | u32 dnctrl; |
| 270 | u32 crcr_lo; |
| 271 | u32 crcr_hi; |
| 272 | #define CRCR_RCS 1<<0 |
| 273 | #define CRCR_CS 1<<1 |
| 274 | #define CRCR_CA 1<<2 |
| 275 | #define CRCR_CRR 1<<3 |
| 276 | u8 res2[0x2f-0x20+1]; |
| 277 | u32 dcbaap_lo; |
| 278 | u32 dcbaap_hi; |
| 279 | u32 config; |
| 280 | #define CONFIG_MASK_MaxSlotsEn 0xff |
| 281 | u8 res3[0x3ff-0x3c+1]; |
| 282 | struct { |
| 283 | u32 portsc; |
| 284 | #define PORTSC_CCS 1<<0 |
| 285 | #define PORTSC_PED 1<<1 |
| 286 | // BIT 2 rsvdZ |
| 287 | #define PORTSC_OCA 1<<3 |
| 288 | #define PORTSC_PR 1<<4 |
| 289 | #define PORTSC_PLS 1<<5 |
| 290 | #define PORTSC_PLS_MASK MASK(5, 4) |
| 291 | #define PORTSC_PP 1<<9 |
| 292 | #define PORTSC_PORT_SPEED 1<<10 |
| 293 | #define PORTSC_PORT_SPEED_MASK MASK(10, 4) |
| 294 | #define PORTSC_PIC 1<<14 |
| 295 | #define PORTSC_PIC_MASK MASK(14, 2) |
| 296 | #define PORTSC_LWS 1<<16 |
| 297 | #define PORTSC_CSC 1<<17 |
| 298 | #define PORTSC_PEC 1<<18 |
| 299 | #define PORTSC_WRC 1<<19 |
| 300 | #define PORTSC_OCC 1<<20 |
| 301 | #define PORTSC_PRC 1<<21 |
| 302 | #define PORTSC_PLC 1<<22 |
| 303 | #define PORTSC_CEC 1<<23 |
| 304 | #define PORTSC_CAS 1<<24 |
| 305 | #define PORTSC_WCE 1<<25 |
| 306 | #define PORTSC_WDE 1<<26 |
| 307 | #define PORTSC_WOE 1<<27 |
| 308 | // BIT 29:28 rsvdZ |
| 309 | #define PORTSC_DR 1<<30 |
| 310 | #define PORTSC_WPR 1<<31 |
| 311 | #define PORTSC_RW_MASK PORTSC_PR | PORTSC_PLS_MASK | PORTSC_PP | PORTSC_PIC_MASK | PORTSC_LWS | PORTSC_WCE | PORTSC_WDE | PORTSC_WOE |
| 312 | u32 portpmsc; |
| 313 | u32 portli; |
| 314 | u32 res; |
| 315 | } __attribute__ ((packed)) prs[]; |
| 316 | } __attribute__ ((packed)) *opreg; |
| 317 | |
| 318 | /* R/W, volatile, MMIO -> no bitfields */ |
| 319 | volatile struct hcrreg { |
| 320 | u32 mfindex; |
| 321 | u8 res1[0x20-0x4]; |
| 322 | struct { |
| 323 | u32 iman; |
| 324 | u32 imod; |
| 325 | u32 erstsz; |
| 326 | u32 res; |
| 327 | u32 erstba_lo; |
| 328 | u32 erstba_hi; |
| 329 | u32 erdp_lo; |
| 330 | u32 erdp_hi; |
| 331 | } __attribute__ ((packed)) intrrs[]; // up to 1024, but maximum host specific, given in capreg->MaxIntrs |
| 332 | } __attribute__ ((packed)) *hcrreg; |
| 333 | |
| 334 | /* R/W, volatile, MMIO -> no bitfields */ |
| 335 | volatile u32 *dbreg; |
| 336 | |
| 337 | /* R/W, volatile, Memory -> bitfields allowed */ |
| 338 | volatile devctxp_t *dcbaa; |
| 339 | |
| 340 | trb_t *cmd_ring; |
| 341 | trb_t *ev_ring; |
| 342 | volatile erst_entry_t *ev_ring_table; |
| 343 | int cmd_ccs, ev_ccs; |
| 344 | |
| 345 | usbdev_t *roothub; |
| 346 | } xhci_t; |
| 347 | |
| 348 | #define XHCI_INST(controller) ((xhci_t*)((controller)->instance)) |
| 349 | |
| 350 | #endif |