From 6615ef3bfc3ff20643a31f01e40473e174460b46 Mon Sep 17 00:00:00 2001 From: Patrick Georgi Date: Fri, 13 Aug 2010 09:18:58 +0000 Subject: Add support for OHCI controllers and prelimiary support for xHCI (USB3) controllers. Improve scanning for USB controllers. Limitations: - OHCI doesn't support interrupt transfers yet (ie. no keyboards) - xHCI just does initialization and device attach/detach so far Signed-off-by: Patrick Georgi Acked-by: Peter Stuge git-svn-id: svn://svn.coreboot.org/coreboot/trunk@5691 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- payloads/libpayload/drivers/usb/xhci_private.h | 350 +++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 payloads/libpayload/drivers/usb/xhci_private.h (limited to 'payloads/libpayload/drivers/usb/xhci_private.h') diff --git a/payloads/libpayload/drivers/usb/xhci_private.h b/payloads/libpayload/drivers/usb/xhci_private.h new file mode 100644 index 0000000000..16834f77cc --- /dev/null +++ b/payloads/libpayload/drivers/usb/xhci_private.h @@ -0,0 +1,350 @@ +/* + * This file is part of the libpayload project. + * + * Copyright (C) 2010 Patrick Georgi + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __XHCI_PRIVATE_H +#define __XHCI_PRIVATE_H + +#include + +#define MASK(startbit, lenbit) (((1<<(lenbit))-1)<<(startbit)) + +typedef volatile union trb { + // transfer + + // events +#define TRB_EV_CMD_CMPL 33 + struct { + u32 Cmd_TRB_Pointer_lo; + u32 Cmd_TRB_Pointer_hi; + struct { + unsigned long:24; + unsigned long Completion_Code:8; + } __attribute__ ((packed)); + struct { + unsigned long C:1; + unsigned long:9; + unsigned long TRB_Type:6; + unsigned long VF_ID:8; + unsigned long Slot_ID:8; + } __attribute__ ((packed)); + } __attribute__ ((packed)) event_cmd_cmpl; + +#define TRB_EV_PORTSC 34 + struct { + struct { + unsigned long:24; + unsigned long Port:8; + } __attribute__ ((packed)); + u32 rsvd; + struct { + unsigned long:24; + unsigned long Completion_Code:8; + } __attribute__ ((packed)); + struct { + unsigned long C:1; + unsigned long:9; + unsigned long TRB_Type:6; + unsigned long:16; + } __attribute__ ((packed)); + } __attribute__ ((packed)) event_portsc; + + // commands +#define TRB_CMD_NOOP 23 + struct { + u32 rsvd[3]; + struct { + unsigned long C:1; + unsigned long:9; + unsigned long TRB_Type:6; + unsigned long:16; + } __attribute__ ((packed)); + } __attribute__ ((packed)) cmd_No_Op; + + // "others" + struct { + u32 Ring_Segment_Ptr_lo; + u32 Ring_Segment_Ptr_hi; + struct { + unsigned long:22; + unsigned long Interrupter_Target; + } __attribute__ ((packed)); + struct { + unsigned long C:1; + unsigned long TC:1; + unsigned long:2; + unsigned long CH:1; + unsigned long IOC:1; + unsigned long:4; + unsigned long TRB_Type:6; + unsigned long:16; + } __attribute__ ((packed)); + } __attribute__ ((packed)) link; +} trb_t; + +typedef struct slotctx { + struct { + unsigned long Route_String:20; + unsigned long Speed:4; + unsigned long:1; + unsigned long MTT:1; + unsigned long Hub:1; + unsigned long Context_Entries:5; + } __attribute__ ((packed)); + struct { + unsigned long Max_Exit_Latency:16; + unsigned long Root_Hub_Port_Number:8; + unsigned long Number_of_Ports:8; + } __attribute__ ((packed)); + struct { + unsigned long TT_Hub_Slot_ID:8; + unsigned long TT_Port_Number:8; + unsigned long TTT:2; + unsigned long:4; + unsigned long Interrupter_Target:10; + } __attribute__ ((packed)); + struct { + unsigned long USB_Device_Address:8; + unsigned long:19; + unsigned long Slot_State:5; + } __attribute__ ((packed)); + u32 rsvd[4]; +} slotctx_t; + +typedef struct epctx { + struct { + unsigned long EP_State:3; + unsigned long:5; + unsigned long Mult:2; + unsigned long MaxPStreams:5; + unsigned long LSA:1; + unsigned long Interval:8; + unsigned long:8; + } __attribute__ ((packed)); + struct { + unsigned long:1; + unsigned long CErr:2; + unsigned long EP_Type:3; + unsigned long:1; + unsigned long HID:1; + unsigned long Max_Burst_Size:8; + unsigned long Max_Packet_Size:16; + } __attribute__ ((packed)); + union { + u32 TR_Dequeue_Pointer_lo; + struct { + unsigned long DCS:1; + unsigned long:3; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + u32 TR_Dequeue_Pointer_hi; + struct { + unsigned long Average_TRB_Length:16; + unsigned long Max_ESIT_Payload:16; + } __attribute__ ((packed)); + u32 rsvd[3]; +} epctx_t; + +typedef struct devctx { + slotctx_t slot; + epctx_t ep0; + struct { + epctx_t out; + epctx_t in; + } eps[15]; +} devctx_t; + +typedef struct devctxp { + devctx_t *ptr; + void *upper; +} devctxp_t; + +typedef struct erst_entry { + u32 seg_base_lo; + u32 seg_base_hi; + u32 seg_size; + u32 rsvd; +} erst_entry_t; + +typedef struct xhci { + /* capreg is read-only, so no need for volatile, + and thus 32bit accesses can be assumed. */ + struct capreg { + u8 caplength; + u8 res1; + union { + u16 hciversion; + struct { + u8 hciver_lo; + u8 hciver_hi; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + union { + u32 hcsparams1; + struct { + unsigned long MaxSlots:7; + unsigned long MaxIntrs:11; + unsigned long:6; + unsigned long MaxPorts:8; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + union { + u32 hcsparams2; + struct { + unsigned long IST:4; + unsigned long ERST_Max:4; + unsigned long:18; + unsigned long SPR:1; + unsigned long Max_Scratchpad_Bufs:5; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + union { + u32 hcsparams3; + struct { + unsigned long u1latency:8; + unsigned long:8; + unsigned long u2latency:16; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + union { + u32 hccparams; + struct { + unsigned long ac64:1; + unsigned long bnc:1; + unsigned long csz:1; + unsigned long ppc:1; + unsigned long pind:1; + unsigned long lhrc:1; + unsigned long ltc:1; + unsigned long nss:1; + unsigned long:4; + unsigned long MaxPSASize:4; + unsigned long xECP:16; + } __attribute__ ((packed)); + } __attribute__ ((packed)); + u32 dboff; + u32 rtsoff; + } __attribute__ ((packed)) *capreg; + + /* opreg is R/W is most places, so volatile access is necessary. + volatile means that the compiler seeks byte writes if possible, + making bitfields unusable for MMIO register blocks. Yay C :-( */ + volatile struct opreg { + u32 usbcmd; +#define USBCMD_RS 1<<0 +#define USBCMD_HCRST 1<<1 + u32 usbsts; +#define USBSTS_HCH 1<<0 +#define USBSTS_HSE 1<<2 +#define USBSTS_EINT 1<<3 +#define USBSTS_PCD 1<<4 +#define USBSTS_CNR 1<<11 + u32 pagesize; + u8 res1[0x13-0x0c+1]; + u32 dnctrl; + u32 crcr_lo; + u32 crcr_hi; +#define CRCR_RCS 1<<0 +#define CRCR_CS 1<<1 +#define CRCR_CA 1<<2 +#define CRCR_CRR 1<<3 + u8 res2[0x2f-0x20+1]; + u32 dcbaap_lo; + u32 dcbaap_hi; + u32 config; +#define CONFIG_MASK_MaxSlotsEn 0xff + u8 res3[0x3ff-0x3c+1]; + struct { + u32 portsc; +#define PORTSC_CCS 1<<0 +#define PORTSC_PED 1<<1 + // BIT 2 rsvdZ +#define PORTSC_OCA 1<<3 +#define PORTSC_PR 1<<4 +#define PORTSC_PLS 1<<5 +#define PORTSC_PLS_MASK MASK(5, 4) +#define PORTSC_PP 1<<9 +#define PORTSC_PORT_SPEED 1<<10 +#define PORTSC_PORT_SPEED_MASK MASK(10, 4) +#define PORTSC_PIC 1<<14 +#define PORTSC_PIC_MASK MASK(14, 2) +#define PORTSC_LWS 1<<16 +#define PORTSC_CSC 1<<17 +#define PORTSC_PEC 1<<18 +#define PORTSC_WRC 1<<19 +#define PORTSC_OCC 1<<20 +#define PORTSC_PRC 1<<21 +#define PORTSC_PLC 1<<22 +#define PORTSC_CEC 1<<23 +#define PORTSC_CAS 1<<24 +#define PORTSC_WCE 1<<25 +#define PORTSC_WDE 1<<26 +#define PORTSC_WOE 1<<27 + // BIT 29:28 rsvdZ +#define PORTSC_DR 1<<30 +#define PORTSC_WPR 1<<31 +#define PORTSC_RW_MASK PORTSC_PR | PORTSC_PLS_MASK | PORTSC_PP | PORTSC_PIC_MASK | PORTSC_LWS | PORTSC_WCE | PORTSC_WDE | PORTSC_WOE + u32 portpmsc; + u32 portli; + u32 res; + } __attribute__ ((packed)) prs[]; + } __attribute__ ((packed)) *opreg; + + /* R/W, volatile, MMIO -> no bitfields */ + volatile struct hcrreg { + u32 mfindex; + u8 res1[0x20-0x4]; + struct { + u32 iman; + u32 imod; + u32 erstsz; + u32 res; + u32 erstba_lo; + u32 erstba_hi; + u32 erdp_lo; + u32 erdp_hi; + } __attribute__ ((packed)) intrrs[]; // up to 1024, but maximum host specific, given in capreg->MaxIntrs + } __attribute__ ((packed)) *hcrreg; + + /* R/W, volatile, MMIO -> no bitfields */ + volatile u32 *dbreg; + + /* R/W, volatile, Memory -> bitfields allowed */ + volatile devctxp_t *dcbaa; + + trb_t *cmd_ring; + trb_t *ev_ring; + volatile erst_entry_t *ev_ring_table; + int cmd_ccs, ev_ccs; + + usbdev_t *roothub; +} xhci_t; + +#define XHCI_INST(controller) ((xhci_t*)((controller)->instance)) + +#endif -- cgit v1.2.3