update xhci driver
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,183 +1,38 @@
|
||||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: usb_hc_xhci.h
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: This files is for xhci data structure definition
|
||||
*
|
||||
* Modify History:
|
||||
* Description: This file is for xhci data structure definition.
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
|
||||
#ifndef USB_HC_XHCI_H
|
||||
#define USB_HC_XHCI_H
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include "usbh_core.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
|
||||
/************************** Type Definitions *****************************/
|
||||
/* slot context */
|
||||
struct xhci_slotctx {
|
||||
uint32_t ctx[4];
|
||||
#define XHCI_SLOTCTX_0_MAX_EPID_SET(maxid) XHCI32_SET_BITS(maxid, 31, 27)
|
||||
#define XHCI_SLOTCTX_0_SPEED_SET(speed) XHCI32_SET_BITS(speed, 23, 20)
|
||||
#define XHCI_SLOTCTX_1_ROOT_PORT_GET(val) XHCI32_GET_BITS(val, 23, 16)
|
||||
#define XHCI_SLOTCTX_1_ROOT_PORT_SET(port) XHCI32_SET_BITS(port, 23, 16)
|
||||
#define XHCI_SLOTCTX_0_ROUTE_SET(route) XHCI32_SET_BITS(route, 19, 0)
|
||||
#define XHCI_SLOTCTX_0_ROUTE_GET(route) XHCI32_GET_BITS(route, 19, 0)
|
||||
#define XHCI_SLOTCTX_2_HUB_SLOT_SET(slot) XHCI32_SET_BITS(slot, 7, 0)
|
||||
#define XHCI_SLOTCTX_2_HUB_SLOT_GET(slot) XHCI32_GET_BITS(slot, 7, 0)
|
||||
#define XHCI_SLOTCTX_2_HUB_PORT_SET(port) XHCI32_SET_BITS(port, 15, 8)
|
||||
#define XHCI_SLOTCTX_2_HUB_PORT_GET(port) XHCI32_GET_BITS(port, 15, 8)
|
||||
#define XHCI_SLOTCTX_3_SLOT_STATE_GET(ctx) XHCI32_GET_BITS(ctx, 31, 27)
|
||||
uint32_t reserved_01[4];
|
||||
#define XHCI_SLOTCTX_ENTRY_NUM 32U
|
||||
#define XHCI_SLOTCTX_ALIGMENT 1024U
|
||||
} __PACKED;
|
||||
|
||||
enum xhci_slot_state {
|
||||
XHCI_SLOT_DEFAULT = 1,
|
||||
XHCI_SLOT_ADDRESS = 2,
|
||||
XHCI_SLOT_CONFIG = 3
|
||||
};
|
||||
|
||||
/* endpoint context */
|
||||
struct xhci_epctx {
|
||||
uint32_t ctx[2];
|
||||
#define XHCI_EPCTX_0_EP_STATE_GET(ctx) XHCI32_GET_BITS(ctx, 2, 0)
|
||||
#define XHCI_EPCTX_0_INTERVAL_SET(interval) XHCI32_SET_BITS(interval, 23, 16)
|
||||
#define XHCI_EPCTX_1_MPS_SET(mps) XHCI32_SET_BITS(mps, 31, 16)
|
||||
#define XHCI_EPCTX_1_MPS_GET(ctx) XHCI32_GET_BITS(ctx, 31, 16)
|
||||
#define XHCI_EPCTX_1_EPTYPE_GET(ctx) XHCI32_GET_BITS(ctx, 5, 3)
|
||||
#define XHCI_EPCTX_1_CERR_SET(cerr) XHCI32_SET_BITS(cerr, 2, 1)
|
||||
uint32_t deq_low;
|
||||
uint32_t deq_high;
|
||||
uint32_t length;
|
||||
#define XHCI_EPCTX_AVE_TRB_LEN_SET(len) XHCI32_SET_BITS(len, 15, 0)
|
||||
#define XHCI_EPCTX_MAX_ESIT_SET(esit) XHCI32_SET_BITS(esit, 31, 16)
|
||||
uint32_t reserved_01[3];
|
||||
} __PACKED;
|
||||
|
||||
/* device context array element */
|
||||
struct xhci_devlist {
|
||||
uint32_t ptr_low;
|
||||
uint32_t ptr_high;
|
||||
} __PACKED;
|
||||
|
||||
/* input context */
|
||||
struct xhci_inctx {
|
||||
uint32_t del;
|
||||
uint32_t add;
|
||||
uint32_t reserved_01[6];
|
||||
/* refer to spec. The Input Context is an array of up to 33 context data structure entries */
|
||||
#define XHCI_INCTX_ENTRY_NUM 33U
|
||||
#define XHCI_INCTX_ALIGMENT 2048
|
||||
} __PACKED;
|
||||
|
||||
/* transfer block (ring element) */
|
||||
struct xhci_trb {
|
||||
uint32_t ptr_low;
|
||||
uint32_t ptr_high;
|
||||
uint32_t status;
|
||||
uint32_t control;
|
||||
} __PACKED;
|
||||
|
||||
/* event ring segment */
|
||||
struct xhci_er_seg {
|
||||
uint32_t ptr_low;
|
||||
uint32_t ptr_high;
|
||||
uint32_t size;
|
||||
uint32_t reserved_01;
|
||||
} __PACKED;
|
||||
|
||||
struct xhci_portmap {
|
||||
uint8_t start;
|
||||
uint8_t count;
|
||||
};
|
||||
|
||||
struct xhci_ring {
|
||||
struct xhci_trb ring[XHCI_RING_ITEMS];
|
||||
struct xhci_trb evt;
|
||||
uint32_t eidx;
|
||||
uint32_t nidx;
|
||||
uint32_t cs;
|
||||
usb_osal_mutex_t lock;
|
||||
};
|
||||
|
||||
struct xhci_pipe {
|
||||
struct xhci_ring reqs; /* DO NOT MOVE reqs from structure beg */
|
||||
uint8_t epaddr;
|
||||
uint8_t speed;
|
||||
uint8_t interval;
|
||||
uint8_t eptype;
|
||||
uint16_t maxpacket;
|
||||
uint32_t slotid;
|
||||
uint32_t epid;
|
||||
|
||||
/* command or transfer waiter */
|
||||
int timeout; /* = 0 no need to wait */
|
||||
bool waiter;
|
||||
usb_osal_sem_t waitsem;
|
||||
|
||||
/* handle urb */
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_urb *urb; /* NULL if no active URB */
|
||||
};
|
||||
|
||||
struct xhci_s {
|
||||
/* devinfo */
|
||||
uint32_t ports;
|
||||
uint32_t slots;
|
||||
bool context64;
|
||||
struct xhci_portmap usb2;
|
||||
struct xhci_portmap usb3;
|
||||
|
||||
/* xhci registers base addr */
|
||||
unsigned long base; /* register base */
|
||||
unsigned long caps; /* capability register base */
|
||||
unsigned long op; /* operational register base */
|
||||
unsigned long pr; /* port register base */
|
||||
unsigned long ir; /* interrupt runtime register base */
|
||||
unsigned long db; /* doorbell register base */
|
||||
unsigned long xcap; /* extended capability */
|
||||
uint32_t hcs[3]; /* capability cache */
|
||||
uint32_t hcc;
|
||||
uint16_t version; /* xhci version */
|
||||
|
||||
/* xhci data structures */
|
||||
struct xhci_devlist *devs;
|
||||
struct xhci_ring *cmds;
|
||||
struct xhci_ring *evts;
|
||||
struct xhci_er_seg *eseg;
|
||||
};
|
||||
/************************** Variable Definitions *****************************/
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
2563
port/xhci/xhci.c
Normal file
2563
port/xhci/xhci.c
Normal file
File diff suppressed because it is too large
Load Diff
940
port/xhci/xhci.h
Normal file
940
port/xhci/xhci.h
Normal file
@@ -0,0 +1,940 @@
|
||||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: xhci.h
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: This file is for xhci register definition.
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
#ifndef XHCI_H
|
||||
#define XHCI_H
|
||||
|
||||
#include "xhci_reg.h"
|
||||
|
||||
#include "usbh_core.h"
|
||||
|
||||
/** @file
|
||||
*
|
||||
* USB eXtensible Host Controller Interface (xHCI) driver
|
||||
*
|
||||
*/
|
||||
|
||||
#define XHCI_RING_ITEMS 16U
|
||||
#define XHCI_ALIGMENT 64U
|
||||
#define XHCI_RING_SIZE (XHCI_RING_ITEMS * sizeof(union xhci_trb))
|
||||
|
||||
/*
|
||||
* xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
|
||||
* then we can get it from a trb pointer (provided by evt ring).
|
||||
*/
|
||||
#define XHCI_RING(_trb) \
|
||||
((struct xhci_ring*)((unsigned long)(_trb) & ~(XHCI_RING_SIZE-1)))
|
||||
|
||||
/** Device context base address array */
|
||||
struct xhci_dcbaa {
|
||||
/** Context base addresses */
|
||||
uint64_t *context;
|
||||
};
|
||||
|
||||
/** Scratchpad buffer */
|
||||
struct xhci_scratchpad {
|
||||
/** Number of page-sized scratchpad buffers */
|
||||
unsigned int count;
|
||||
/** Scratchpad buffer area */
|
||||
uintptr_t buffer;
|
||||
/** Scratchpad array */
|
||||
uint64_t *array;
|
||||
};
|
||||
|
||||
/** An input control context */
|
||||
struct xhci_control_context {
|
||||
/** Drop context flags */
|
||||
uint32_t drop;
|
||||
/** Add context flags */
|
||||
uint32_t add;
|
||||
/** Reserved */
|
||||
uint32_t reserved_a[5];
|
||||
/** Configuration value */
|
||||
uint8_t config;
|
||||
/** Interface number */
|
||||
uint8_t intf;
|
||||
/** Alternate setting */
|
||||
uint8_t alt;
|
||||
/** Reserved */
|
||||
uint8_t reserved_b;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A slot context */
|
||||
struct xhci_slot_context {
|
||||
/** Device info 03-00h */
|
||||
uint32_t info;
|
||||
/** Maximum exit latency */
|
||||
uint16_t latency;
|
||||
/** Root hub port number */
|
||||
uint8_t port;
|
||||
/** Number of downstream ports 07-04h */
|
||||
uint8_t ports;
|
||||
/** TT hub slot ID */
|
||||
uint8_t tt_id;
|
||||
/** TT port number */
|
||||
uint8_t tt_port;
|
||||
/** Interrupter target 0b-08h */
|
||||
uint16_t intr;
|
||||
/** USB address */
|
||||
uint8_t address;
|
||||
/** Reserved */
|
||||
uint16_t reserved_a;
|
||||
/** Slot state 0f-0ch */
|
||||
uint8_t state;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b[4];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Construct slot context device info */
|
||||
#define XHCI_SLOT_INFO( entries, hub, speed, route ) \
|
||||
( ( (entries) << 27 ) | ( (hub) << 26 ) | ( (speed) << 20 ) | (route) )
|
||||
|
||||
/** An endpoint context */
|
||||
struct xhci_endpoint_context {
|
||||
/** Endpoint state 03-00h*/
|
||||
uint8_t state;
|
||||
/** Stream configuration */
|
||||
uint8_t stream;
|
||||
#define XHCI_EPCTX_MULT_GET(stream) XHCI32_GET_BITS(stream, 1, 0)
|
||||
#define XHCI_EPCTX_STREAM_GET(stream) XHCI32_GET_BITS(stream, 6, 2)
|
||||
#define XHCI_EPCTX_LSA BIT(7)
|
||||
/** Polling interval */
|
||||
uint8_t interval;
|
||||
/** Max ESIT payload high */
|
||||
uint8_t esit_high;
|
||||
/** Endpoint type 04-04h */
|
||||
uint8_t type;
|
||||
#define XHCI_EPCTX_CERR_GET(type) XHCI32_GET_BITS(type, 2, 1)
|
||||
#define XHCI_EPCTX_TYPE_GET(type) XHCI32_GET_BITS(type, 5, 3)
|
||||
#define XHCI_EPCTX_HID BIT(7)
|
||||
/** Maximum burst size */
|
||||
uint8_t burst;
|
||||
/** Maximum packet size */
|
||||
uint16_t mtu;
|
||||
/** Transfer ring dequeue pointer 0f-08h */
|
||||
uint64_t dequeue;
|
||||
#define XHCI_EPCTX_DCS BIT(0)
|
||||
/** Average TRB length 13-10h */
|
||||
uint16_t trb_len;
|
||||
/** Max ESIT payload low */
|
||||
uint16_t esit_low;
|
||||
/** Reserved */
|
||||
uint32_t reserved[3];
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Endpoint states */
|
||||
enum {
|
||||
/** Endpoint is disabled */
|
||||
XHCI_ENDPOINT_DISABLED = 0,
|
||||
/** Endpoint is running */
|
||||
XHCI_ENDPOINT_RUNNING = 1,
|
||||
/** Endpoint is halted due to a USB Halt condition */
|
||||
XHCI_ENDPOINT_HALTED = 2,
|
||||
/** Endpoint is stopped */
|
||||
XHCI_ENDPOINT_STOPPED = 3,
|
||||
/** Endpoint is halted due to a TRB error */
|
||||
XHCI_ENDPOINT_ERROR = 4,
|
||||
};
|
||||
|
||||
/** Endpoint state mask */
|
||||
#define XHCI_ENDPOINT_STATE_MASK 0x07
|
||||
|
||||
/** Endpoint type */
|
||||
#define XHCI_EP_TYPE(type) ( (type) << 3 )
|
||||
|
||||
/** Control endpoint type */
|
||||
#define XHCI_EP_TYPE_CONTROL XHCI_EP_TYPE ( 4 )
|
||||
|
||||
/** Input endpoint type */
|
||||
#define XHCI_EP_TYPE_IN XHCI_EP_TYPE ( 4 )
|
||||
|
||||
/** Periodic endpoint type */
|
||||
#define XHCI_EP_TYPE_PERIODIC XHCI_EP_TYPE ( 1 )
|
||||
|
||||
/** Endpoint dequeue cycle state */
|
||||
#define XHCI_EP_DCS 0x00000001UL
|
||||
|
||||
/** Control endpoint average TRB length */
|
||||
#define XHCI_EP0_TRB_LEN 8
|
||||
|
||||
/**
|
||||
* Calculate doorbell register value
|
||||
*
|
||||
* @v target Doorbell target
|
||||
* @v stream Doorbell stream ID
|
||||
* @ret dbval Doorbell register value
|
||||
*/
|
||||
#define XHCI_DBVAL( target, stream ) ( (target) | ( (stream) << 16 ) )
|
||||
|
||||
|
||||
/** Slot context index */
|
||||
#define XHCI_CTX_SLOT 0
|
||||
|
||||
/** Calculate context index from USB endpoint address */
|
||||
/* refer to spec. Figure 4-4: Endpoint Context Addressing
|
||||
ep0 = 1, ep1-out = 2, ep1-in = 3, ... ep15-out = 30, ep15-in = 31 */
|
||||
#define XHCI_CTX(address) \
|
||||
( (address) ? ( ( ( (address) & 0x0f ) << 1 ) | \
|
||||
( ( (address) & 0x80 ) >> 7 ) ) : 1 )
|
||||
|
||||
/** Endpoint zero context index */
|
||||
#define XHCI_CTX_EP0 XHCI_CTX ( 0x00 )
|
||||
|
||||
/** End of contexts */
|
||||
#define XHCI_CTX_END 32
|
||||
|
||||
/** Device context index */
|
||||
#define XHCI_DCI(ctx) ( (ctx) + 0 )
|
||||
|
||||
/** Input context index */
|
||||
#define XHCI_ICI(ctx) ( (ctx) + 1 )
|
||||
|
||||
/** Number of TRBs (excluding Link TRB) in the command ring
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_CMD_TRBS_LOG2 2
|
||||
|
||||
/** Number of TRBs in the event ring
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_EVENT_TRBS_LOG2 6
|
||||
|
||||
/** Number of TRBs in a transfer ring
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_TRANSFER_TRBS_LOG2 6
|
||||
|
||||
/** Maximum time to wait for BIOS to release ownership
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_USBLEGSUP_MAX_WAIT_MS 100
|
||||
|
||||
/** Maximum time to wait for host controller to stop
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_STOP_MAX_WAIT_MS 100
|
||||
|
||||
/** Maximum time to wait for reset to complete
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_RESET_MAX_WAIT_MS 500
|
||||
|
||||
/** Maximum time to wait for a command to complete
|
||||
*
|
||||
* The "address device" command involves waiting for a response to a
|
||||
* USB control transaction, and so we must wait for up to the 5000ms
|
||||
* that USB allows for devices to respond to control transactions.
|
||||
*/
|
||||
#define XHCI_COMMAND_MAX_WAIT_MS 5000
|
||||
|
||||
/** Time to delay after aborting a command
|
||||
*
|
||||
* This is a policy decision
|
||||
*/
|
||||
#define XHCI_COMMAND_ABORT_DELAY_MS 500
|
||||
|
||||
/** Maximum time to wait for a port reset to complete
|
||||
*
|
||||
* This is a policy decision.
|
||||
*/
|
||||
#define XHCI_PORT_RESET_MAX_WAIT_MS 500
|
||||
|
||||
/** A transfer request block template */
|
||||
struct xhci_trb_template {
|
||||
/** Parameter */
|
||||
uint64_t parameter;
|
||||
/** Status */
|
||||
uint32_t status;
|
||||
/** Control */
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
/** A transfer request block */
|
||||
struct xhci_trb_common {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint16_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** Transfer request block cycle bit flag */
|
||||
#define XHCI_TRB_C 0x01
|
||||
|
||||
/** Transfer request block toggle cycle bit flag */
|
||||
#define XHCI_TRB_TC 0x02
|
||||
|
||||
/** Transfer request block chain flag */
|
||||
#define XHCI_TRB_CH 0x10
|
||||
|
||||
/** Transfer request block interrupt on completion flag */
|
||||
#define XHCI_TRB_IOC 0x20
|
||||
|
||||
/** Transfer request block immediate data flag */
|
||||
#define XHCI_TRB_IDT 0x40
|
||||
|
||||
/** Transfer request block type */
|
||||
#define XHCI_TRB_TYPE(type) ( (type) << 2 )
|
||||
|
||||
/** Transfer request block type mask */
|
||||
#define XHCI_TRB_TYPE_MASK XHCI_TRB_TYPE ( 0x3f )
|
||||
|
||||
/** A normal transfer request block */
|
||||
struct xhci_trb_normal {
|
||||
/** Data buffer */
|
||||
uint64_t data;
|
||||
/** Length */
|
||||
uint32_t len;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint16_t reserved;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A normal transfer request block */
|
||||
#define XHCI_TRB_NORMAL XHCI_TRB_TYPE ( 1 )
|
||||
|
||||
/** Construct TD size field */
|
||||
#define XHCI_TD_SIZE(remaining) \
|
||||
( ( ( (remaining) <= 0xf ) ? remaining : 0xf ) << 17 )
|
||||
|
||||
/** A setup stage transfer request block */
|
||||
struct xhci_trb_setup {
|
||||
/** Setup packet, 04-00h sw will copy request content to this field */
|
||||
struct usb_setup_packet packet;
|
||||
/** Length 08h */
|
||||
uint32_t len;
|
||||
/** Flags 0ch */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Transfer direction */
|
||||
uint8_t direction;
|
||||
/** Reserved */
|
||||
uint8_t reserved;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A setup stage transfer request block */
|
||||
#define XHCI_TRB_SETUP XHCI_TRB_TYPE ( 2 )
|
||||
|
||||
/** Setup stage input data direction */
|
||||
#define XHCI_SETUP_IN 3
|
||||
|
||||
/** Setup stage output data direction */
|
||||
#define XHCI_SETUP_OUT 2
|
||||
|
||||
/** A data stage transfer request block */
|
||||
struct xhci_trb_data {
|
||||
/** Data buffer */
|
||||
uint64_t data;
|
||||
/** Length */
|
||||
uint32_t len;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Transfer direction */
|
||||
uint8_t direction;
|
||||
/** Reserved */
|
||||
uint8_t reserved;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A data stage transfer request block */
|
||||
#define XHCI_TRB_DATA XHCI_TRB_TYPE ( 3 )
|
||||
|
||||
/** Input data direction */
|
||||
#define XHCI_DATA_IN 0x01
|
||||
|
||||
/** Output data direction */
|
||||
#define XHCI_DATA_OUT 0x00
|
||||
|
||||
/** A status stage transfer request block */
|
||||
struct xhci_trb_status {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Direction */
|
||||
uint8_t direction;
|
||||
/** Reserved */
|
||||
uint8_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A status stage transfer request block */
|
||||
#define XHCI_TRB_STATUS XHCI_TRB_TYPE ( 4 )
|
||||
|
||||
/** Input status direction */
|
||||
#define XHCI_STATUS_IN 0x01
|
||||
|
||||
/** Output status direction */
|
||||
#define XHCI_STATUS_OUT 0x00
|
||||
|
||||
/** A link transfer request block */
|
||||
struct xhci_trb_link {
|
||||
/** Next ring segment */
|
||||
uint64_t next;
|
||||
/** Reserved */
|
||||
uint32_t reserved_a;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint16_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A link transfer request block */
|
||||
#define XHCI_TRB_LINK XHCI_TRB_TYPE ( 6 )
|
||||
|
||||
/** A no-op transfer request block */
|
||||
#define XHCI_TRB_NOP XHCI_TRB_TYPE ( 8 )
|
||||
|
||||
/** An enable slot transfer request block */
|
||||
struct xhci_trb_enable_slot {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Slot type */
|
||||
uint8_t slot;
|
||||
/** Reserved */
|
||||
uint8_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** An enable slot transfer request block */
|
||||
#define XHCI_TRB_ENABLE_SLOT XHCI_TRB_TYPE ( 9 )
|
||||
|
||||
/** A disable slot transfer request block */
|
||||
struct xhci_trb_disable_slot {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint8_t reserved_c;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A disable slot transfer request block */
|
||||
#define XHCI_TRB_DISABLE_SLOT XHCI_TRB_TYPE ( 10 )
|
||||
|
||||
/** A context transfer request block */
|
||||
struct xhci_trb_context {
|
||||
/** Input context */
|
||||
uint64_t input;
|
||||
/** Reserved */
|
||||
uint32_t reserved_a;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint8_t reserved_b;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** An address device transfer request block */
|
||||
#define XHCI_TRB_ADDRESS_DEVICE XHCI_TRB_TYPE ( 11 )
|
||||
|
||||
/** A configure endpoint transfer request block */
|
||||
#define XHCI_TRB_CONFIGURE_ENDPOINT XHCI_TRB_TYPE ( 12 )
|
||||
|
||||
/** An evaluate context transfer request block */
|
||||
#define XHCI_TRB_EVALUATE_CONTEXT XHCI_TRB_TYPE ( 13 )
|
||||
|
||||
/** A reset endpoint transfer request block */
|
||||
struct xhci_trb_reset_endpoint {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Endpoint ID */
|
||||
uint8_t endpoint;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A reset endpoint transfer request block */
|
||||
#define XHCI_TRB_RESET_ENDPOINT XHCI_TRB_TYPE ( 14 )
|
||||
|
||||
/** A stop endpoint transfer request block */
|
||||
struct xhci_trb_stop_endpoint {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint32_t reserved_b;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Endpoint ID */
|
||||
uint8_t endpoint;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A stop endpoint transfer request block */
|
||||
#define XHCI_TRB_STOP_ENDPOINT XHCI_TRB_TYPE ( 15 )
|
||||
|
||||
/** A set transfer ring dequeue pointer transfer request block */
|
||||
struct xhci_trb_set_tr_dequeue_pointer {
|
||||
/** Dequeue pointer */
|
||||
uint64_t dequeue;
|
||||
/** Reserved */
|
||||
uint32_t reserved;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Endpoint ID */
|
||||
uint8_t endpoint;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A set transfer ring dequeue pointer transfer request block */
|
||||
#define XHCI_TRB_SET_TR_DEQUEUE_POINTER XHCI_TRB_TYPE ( 16 )
|
||||
|
||||
/** A no-op command transfer request block */
|
||||
#define XHCI_TRB_NOP_CMD XHCI_TRB_TYPE ( 23 )
|
||||
|
||||
/** A transfer event transfer request block */
|
||||
struct xhci_trb_transfer {
|
||||
/** Transfer TRB pointer */
|
||||
uint64_t transfer;
|
||||
/** Residual transfer length */
|
||||
uint16_t residual;
|
||||
/** Reserved */
|
||||
uint8_t reserved;
|
||||
/** Completion code */
|
||||
uint8_t code;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Endpoint ID */
|
||||
uint8_t endpoint;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A transfer event transfer request block */
|
||||
#define XHCI_TRB_TRANSFER XHCI_TRB_TYPE ( 32 )
|
||||
|
||||
/** A command completion event transfer request block */
|
||||
struct xhci_trb_complete {
|
||||
/** Command TRB pointer */
|
||||
uint64_t command;
|
||||
/** Parameter */
|
||||
uint8_t parameter[3];
|
||||
/** Completion code */
|
||||
uint8_t code;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Virtual function ID */
|
||||
uint8_t vf;
|
||||
/** Slot ID */
|
||||
uint8_t slot;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A command completion event transfer request block */
|
||||
#define XHCI_TRB_COMPLETE XHCI_TRB_TYPE ( 33 )
|
||||
|
||||
/** xHCI completion codes */
|
||||
enum xhci_completion_code {
|
||||
/** Timeout */
|
||||
XHCI_CMPLT_TIMEOUT = -1,
|
||||
/** Success */
|
||||
XHCI_CMPLT_SUCCESS = 1,
|
||||
/** Stall Error */
|
||||
XHCI_CMPLT_STALL = 6,
|
||||
/** Bandwidth Error */
|
||||
XHCI_CMPLT_BANDWIDTH = 8,
|
||||
/** Endpoint Not Enabled Error */
|
||||
XHCI_CMPLT_ENDPOINT_NOT_ENABLED = 12,
|
||||
/** Short packet */
|
||||
XHCI_CMPLT_SHORT = 13,
|
||||
/** Parameter Error */
|
||||
XHCI_CMPLT_PARAMETER = 17,
|
||||
/** Command ring stopped */
|
||||
XHCI_CMPLT_CMD_STOPPED = 24,
|
||||
};
|
||||
|
||||
/** A port status change transfer request block */
|
||||
struct xhci_trb_port_status {
|
||||
/** Reserved */
|
||||
uint8_t reserved_a[3];
|
||||
/** Port ID */
|
||||
uint8_t port;
|
||||
/** Reserved */
|
||||
uint8_t reserved_b[7];
|
||||
/** Completion code */
|
||||
uint8_t code;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint16_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A port status change transfer request block */
|
||||
#define XHCI_TRB_PORT_STATUS XHCI_TRB_TYPE ( 34 )
|
||||
|
||||
/** A port status change transfer request block */
|
||||
struct xhci_trb_host_controller {
|
||||
/** Reserved */
|
||||
uint64_t reserved_a;
|
||||
/** Reserved */
|
||||
uint8_t reserved_b[3];
|
||||
/** Completion code */
|
||||
uint8_t code;
|
||||
/** Flags */
|
||||
uint8_t flags;
|
||||
/** Type */
|
||||
uint8_t type;
|
||||
/** Reserved */
|
||||
uint16_t reserved_c;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** A port status change transfer request block */
|
||||
#define XHCI_TRB_HOST_CONTROLLER XHCI_TRB_TYPE ( 37 )
|
||||
|
||||
/** A transfer request block */
|
||||
union xhci_trb {
|
||||
/** Template */
|
||||
struct xhci_trb_template template;
|
||||
/** Common fields */
|
||||
struct xhci_trb_common common;
|
||||
/** Normal TRB */
|
||||
struct xhci_trb_normal normal;
|
||||
/** Setup stage TRB */
|
||||
struct xhci_trb_setup setup;
|
||||
/** Data stage TRB */
|
||||
struct xhci_trb_data data;
|
||||
/** Status stage TRB */
|
||||
struct xhci_trb_status status;
|
||||
/** Link TRB */
|
||||
struct xhci_trb_link link;
|
||||
/** Enable slot TRB */
|
||||
struct xhci_trb_enable_slot enable;
|
||||
/** Disable slot TRB */
|
||||
struct xhci_trb_disable_slot disable;
|
||||
/** Input context TRB */
|
||||
struct xhci_trb_context context;
|
||||
/** Reset endpoint TRB */
|
||||
struct xhci_trb_reset_endpoint reset;
|
||||
/** Stop endpoint TRB */
|
||||
struct xhci_trb_stop_endpoint stop;
|
||||
/** Set transfer ring dequeue pointer TRB */
|
||||
struct xhci_trb_set_tr_dequeue_pointer dequeue;
|
||||
/** Transfer event */
|
||||
struct xhci_trb_transfer transfer;
|
||||
/** Command completion event */
|
||||
struct xhci_trb_complete complete;
|
||||
/** Port status changed event */
|
||||
struct xhci_trb_port_status port;
|
||||
/** Host controller event */
|
||||
struct xhci_trb_host_controller host;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
struct xhci_ring {
|
||||
union xhci_trb ring[XHCI_RING_ITEMS];
|
||||
union xhci_trb evt;
|
||||
uint32_t eidx;
|
||||
uint32_t nidx;
|
||||
uint32_t cs;
|
||||
usb_osal_mutex_t lock;
|
||||
};
|
||||
|
||||
/** An event ring segment */
|
||||
struct xhci_er_seg {
|
||||
/** Base address */
|
||||
uint64_t base;
|
||||
/** Number of TRBs */
|
||||
uint32_t count;
|
||||
/** Reserved */
|
||||
uint32_t reserved;
|
||||
} __attribute__ (( packed ));
|
||||
|
||||
/** An xHCI endpoint */
|
||||
struct xhci_endpoint {
|
||||
struct xhci_ring reqs; /* DO NOT MOVE reqs from structure beg */
|
||||
/** xHCI device */
|
||||
struct xhci_host *xhci;
|
||||
/** xHCI slot */
|
||||
struct xhci_slot *slot;
|
||||
/** Endpoint address */
|
||||
unsigned int address;
|
||||
/** Context index */
|
||||
unsigned int ctx;
|
||||
/** Endpoint type in USB definition */
|
||||
unsigned int ep_type;
|
||||
/** Endpoint type in XHCI Endpoint context definition */
|
||||
unsigned int ctx_type;
|
||||
|
||||
/** Maximum transfer size (Maximum packet size) */
|
||||
unsigned int mtu;
|
||||
/** Maximum burst size */
|
||||
unsigned int burst;
|
||||
/** Endpoint interval */
|
||||
unsigned int interval;
|
||||
|
||||
/** Endpoint context */
|
||||
struct xhci_endpoint_context *context;
|
||||
|
||||
/* command or transfer waiter */
|
||||
int timeout; /* = 0 no need to wait */
|
||||
bool waiter;
|
||||
usb_osal_sem_t waitsem;
|
||||
|
||||
/* handle urb */
|
||||
struct usbh_hubport *hport;
|
||||
struct usbh_urb *urb; /* NULL if no active URB */
|
||||
};
|
||||
|
||||
/** An xHCI device slot */
|
||||
struct xhci_slot {
|
||||
/** xHCI device */
|
||||
struct xhci_host *xhci;
|
||||
/** Slot ID */
|
||||
unsigned int id;
|
||||
/** Slot context */
|
||||
struct xhci_slot_context *context;
|
||||
|
||||
/** Route string */
|
||||
unsigned int route;
|
||||
/** Root hub port number */
|
||||
unsigned int port;
|
||||
/** Protocol speed ID */
|
||||
unsigned int psiv;
|
||||
/** Number of ports (if this device is a hub) */
|
||||
unsigned int ports;
|
||||
/** Transaction translator slot ID */
|
||||
unsigned int tt_id;
|
||||
/** Transaction translator port */
|
||||
unsigned int tt_port;
|
||||
|
||||
/** Endpoints, indexed by context ID */
|
||||
struct xhci_endpoint *endpoint[XHCI_CTX_END];
|
||||
};
|
||||
|
||||
/** An xHCI device */
|
||||
struct xhci_host {
|
||||
/** ID */
|
||||
uint32_t id;
|
||||
/** Name */
|
||||
char name[4];
|
||||
|
||||
/* xhci registers base addr */
|
||||
/** Registers base */
|
||||
void *base;
|
||||
/** Capability registers */
|
||||
void *cap;
|
||||
/** Operational registers */
|
||||
void *op;
|
||||
/** Runtime registers */
|
||||
void *run;
|
||||
/** Doorbell registers */
|
||||
void *db;
|
||||
/** extended capability */
|
||||
unsigned int xecp;
|
||||
/** capability cache */
|
||||
uint32_t hcs[3];
|
||||
uint32_t hcc;
|
||||
/** xhci version */
|
||||
uint16_t version;
|
||||
|
||||
/** Number of device slots */
|
||||
unsigned int slots;
|
||||
/** Number of interrupters */
|
||||
unsigned int intrs;
|
||||
/** Number of ports */
|
||||
unsigned int ports;
|
||||
|
||||
/** 64-bit addressing capability */
|
||||
int addr64;
|
||||
/** Context size shift */
|
||||
unsigned int csz_shift;
|
||||
/** Page size */
|
||||
size_t pagesize;
|
||||
|
||||
/** USB legacy support capability (if present and enabled) */
|
||||
unsigned int legacy;
|
||||
|
||||
/** Device context base address array */
|
||||
struct xhci_dcbaa dcbaa;
|
||||
|
||||
/** Scratchpad buffer */
|
||||
struct xhci_scratchpad scratch;
|
||||
|
||||
/** Device slots, indexed by slot ID */
|
||||
struct xhci_slot **slot;
|
||||
|
||||
/** Command ring */
|
||||
struct xhci_ring *cmds;
|
||||
/** Event ring */
|
||||
struct xhci_ring *evts;
|
||||
struct xhci_er_seg *eseg;
|
||||
|
||||
struct xhci_endpoint *cur_cmd_pipe;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculate input context offset
|
||||
*
|
||||
* @v xhci xHCI device
|
||||
* @v ctx Context index
|
||||
*/
|
||||
static inline size_t xhci_input_context_offset ( struct xhci_host *xhci,
|
||||
unsigned int ctx ) {
|
||||
|
||||
return ( XHCI_ICI ( ctx ) << xhci->csz_shift );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate device context offset
|
||||
*
|
||||
* @v xhci xHCI device
|
||||
* @v ctx Context index
|
||||
*/
|
||||
static inline size_t xhci_device_context_offset ( struct xhci_host *xhci,
|
||||
unsigned int ctx ) {
|
||||
|
||||
return ( XHCI_DCI ( ctx ) << xhci->csz_shift );
|
||||
}
|
||||
|
||||
/* Probe XCHI device */
|
||||
int xhci_probe ( struct xhci_host *xhci, unsigned long baseaddr );
|
||||
|
||||
/* Open XHCI device and start running */
|
||||
int xhci_open ( struct xhci_host *xhci );
|
||||
|
||||
/* Close XHCI device and stop running */
|
||||
void xhci_close ( struct xhci_host *xhci );
|
||||
|
||||
/* Remove XHCI device and free allocated memory */
|
||||
void xhci_remove ( struct xhci_host *xhci );
|
||||
|
||||
/* Enable port */
|
||||
int xhci_port_enable (struct xhci_host *xhci, uint32_t port);
|
||||
|
||||
/* Get port speed */
|
||||
uint32_t xhci_root_speed ( struct xhci_host *xhci, uint8_t port );
|
||||
|
||||
/* Open and enable device */
|
||||
int xhci_device_open ( struct xhci_host *xhci, struct xhci_endpoint *pipe, int *slot_id );
|
||||
|
||||
/* Assign device address */
|
||||
int xhci_device_address ( struct xhci_host *xhci, struct xhci_slot *slot, struct xhci_endpoint *pipe );
|
||||
|
||||
/* Close device and free allocated memory */
|
||||
void xhci_device_close ( struct xhci_slot *slot );
|
||||
|
||||
/* Open control endpoint for slot */
|
||||
int xhci_ctrl_endpoint_open ( struct xhci_host *xhci, struct xhci_slot *slot, struct xhci_endpoint *pipe );
|
||||
|
||||
/* Open work endpoint for slot */
|
||||
int xhci_work_endpoint_open ( struct xhci_host *xhci, struct xhci_slot *slot, struct xhci_endpoint *pipe );
|
||||
|
||||
/* Close endpoint and free allocated memory */
|
||||
void xhci_endpoint_close ( struct xhci_endpoint *ep );
|
||||
|
||||
/* Update MTU (Max packet size) of endpoint */
|
||||
int xhci_endpoint_mtu ( struct xhci_endpoint *ep );
|
||||
|
||||
/* Enqueue message transfer, usually for control transfer */
|
||||
void xhci_endpoint_message ( struct xhci_endpoint *ep, struct usb_setup_packet *packet,
|
||||
void *data_buff, int datalen );
|
||||
|
||||
/* Enqueue stream transfer, usually for bulk/interrupt transfer */
|
||||
void xhci_endpoint_stream ( struct xhci_endpoint *ep, void *data_buff, int datalen );
|
||||
|
||||
/* Process event ring in interrupt */
|
||||
struct xhci_endpoint *xhci_event_process(struct xhci_host *xhci);
|
||||
|
||||
/* Wait for a ring to empty (all TRBs processed by hardware) */
|
||||
int xhci_event_wait(struct xhci_host *xhci,
|
||||
struct xhci_endpoint *pipe,
|
||||
struct xhci_ring *ring);
|
||||
|
||||
/* Dump host controller registers */
|
||||
void xhci_dump(struct xhci_host *xhci);
|
||||
|
||||
/* Dump port registers */
|
||||
void xhci_dump_port ( struct xhci_host *xhci,
|
||||
unsigned int port );
|
||||
|
||||
/* Dump Port status */
|
||||
void xhci_dump_port_status(uint32_t port, uint32_t portsc);
|
||||
|
||||
/* Dump input context */
|
||||
void xhci_dump_input_ctx( struct xhci_host *xhci, const struct xhci_endpoint *endpoint, const void *input);
|
||||
|
||||
/* Dump Endpoint */
|
||||
void xhci_dump_endpoint(const struct xhci_endpoint *ep);
|
||||
|
||||
/* Dump endpoint context */
|
||||
void xhci_dump_ep_ctx(const struct xhci_endpoint_context *ep);
|
||||
|
||||
/* Dump TRB */
|
||||
void xhci_dump_trbs(const union xhci_trb *trbs, unsigned int count);
|
||||
|
||||
/* Dump slot context */
|
||||
void xhci_dump_slot_ctx(const struct xhci_slot_context *const sc);
|
||||
|
||||
#endif /* XHCI_H */
|
||||
353
port/xhci/xhci_dbg.c
Normal file
353
port/xhci/xhci_dbg.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: xhci_dbg.c
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: This file is for implment xhci debug functions
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "usbh_core.h"
|
||||
|
||||
#include "xhci.h"
|
||||
|
||||
/* macro to enable dump */
|
||||
#define XHCI_DUMP 1
|
||||
#define XHCI_DUMP_PORT 1
|
||||
#define XHCI_DUMP_TRB 0
|
||||
#define XHCI_DUMP_SLOT 0
|
||||
#define XHCI_DUMP_EP_CTX 0
|
||||
#define XHCI_DUMP_INPUT_CTX 0
|
||||
#define XHCI_DUMP_ENDPOINT 0
|
||||
#define XHCI_DUMP_PORT_STATUS 0
|
||||
|
||||
/**
|
||||
* Dump host controller registers
|
||||
*
|
||||
* @v xhci xHCI device
|
||||
*/
|
||||
void xhci_dump(struct xhci_host *xhci) {
|
||||
#if XHCI_DUMP
|
||||
uint32_t usbcmd;
|
||||
uint32_t usbsts;
|
||||
uint32_t pagesize;
|
||||
uint32_t dnctrl;
|
||||
uint32_t config;
|
||||
|
||||
/* Dump USBCMD */
|
||||
usbcmd = readl ( xhci->op + XHCI_OP_USBCMD );
|
||||
USB_LOG_DBG ( "XHCI %s USBCMD %08x%s%s\n", xhci->name, usbcmd,
|
||||
( ( usbcmd & XHCI_USBCMD_RUN ) ? " run" : "" ),
|
||||
( ( usbcmd & XHCI_USBCMD_HCRST ) ? " hcrst" : "" ) );
|
||||
|
||||
/* Dump USBSTS */
|
||||
usbsts = readl ( xhci->op + XHCI_OP_USBSTS );
|
||||
USB_LOG_DBG ( "XHCI %s USBSTS %08x%s\n", xhci->name, usbsts,
|
||||
( ( usbsts & XHCI_USBSTS_HCH ) ? " hch" : "" ) );
|
||||
|
||||
/* Dump PAGESIZE */
|
||||
pagesize = readl ( xhci->op + XHCI_OP_PAGESIZE );
|
||||
USB_LOG_DBG ( "XHCI %s PAGESIZE %08x\n", xhci->name, pagesize );
|
||||
|
||||
/* Dump DNCTRL */
|
||||
dnctrl = readl ( xhci->op + XHCI_OP_DNCTRL );
|
||||
USB_LOG_DBG ( "XHCI %s DNCTRL %08x\n", xhci->name, dnctrl );
|
||||
|
||||
/* Dump CONFIG */
|
||||
config = readl ( xhci->op + XHCI_OP_CONFIG );
|
||||
USB_LOG_DBG ( "XHCI %s CONFIG %08x\n", xhci->name, config );
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump port registers
|
||||
*
|
||||
* @v xhci xHCI device
|
||||
* @v port Port number
|
||||
*/
|
||||
void xhci_dump_port ( struct xhci_host *xhci,
|
||||
unsigned int port ) {
|
||||
#if XHCI_DUMP_PORT
|
||||
uint32_t portsc;
|
||||
uint32_t portpmsc;
|
||||
uint32_t portli;
|
||||
uint32_t porthlpmc;
|
||||
|
||||
/* Dump PORTSC */
|
||||
portsc = readl ( xhci->op + XHCI_OP_PORTSC ( port ) );
|
||||
USB_LOG_DBG ( "XHCI %s-%d PORTSC %08x%s%s%s%s psiv=%d\n",
|
||||
xhci->name, port, portsc,
|
||||
( ( portsc & XHCI_PORTSC_CCS ) ? " ccs" : "" ),
|
||||
( ( portsc & XHCI_PORTSC_PED ) ? " ped" : "" ),
|
||||
( ( portsc & XHCI_PORTSC_PR ) ? " pr" : "" ),
|
||||
( ( portsc & XHCI_PORTSC_PP ) ? " pp" : "" ),
|
||||
XHCI_PORTSC_PSIV ( portsc ) );
|
||||
|
||||
/* Dump PORTPMSC */
|
||||
portpmsc = readl ( xhci->op + XHCI_OP_PORTPMSC ( port ) );
|
||||
USB_LOG_DBG ( "XHCI %s-%d PORTPMSC %08x\n", xhci->name, port, portpmsc );
|
||||
|
||||
/* Dump PORTLI */
|
||||
portli = readl ( xhci->op + XHCI_OP_PORTLI ( port ) );
|
||||
USB_LOG_DBG ( "XHCI %s-%d PORTLI %08x\n", xhci->name, port, portli );
|
||||
|
||||
/* Dump PORTHLPMC */
|
||||
porthlpmc = readl ( xhci->op + XHCI_OP_PORTHLPMC ( port ) );
|
||||
USB_LOG_DBG ( "XHCI %s-%d PORTHLPMC %08x\n",
|
||||
xhci->name, port, porthlpmc );
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump slot context
|
||||
*
|
||||
* @v sc Slot context
|
||||
*/
|
||||
void xhci_dump_slot_ctx(const struct xhci_slot_context *const sc) {
|
||||
#if XHCI_DUMP_SLOT
|
||||
const uint8_t *ctx = (uint8_t *)sc;
|
||||
|
||||
USB_LOG_DBG("===== slot ctx ===== \r\n");
|
||||
USB_LOG_DBG("ctx[0]=0x%x\n", *((uint32_t*)ctx));
|
||||
USB_LOG_DBG(" info: 0x%x \r\n", sc->info);
|
||||
USB_LOG_DBG("ctx[1]=0x%x\n", *((uint32_t*)ctx + 1));
|
||||
USB_LOG_DBG(" latency: 0x%x \r\n", sc->latency);
|
||||
USB_LOG_DBG(" port: 0x%x \r\n", sc->port);
|
||||
USB_LOG_DBG(" ports: 0x%x \r\n", sc->ports);
|
||||
USB_LOG_DBG("ctx[2]=0x%x\n", *((uint32_t*)ctx + 2));
|
||||
USB_LOG_DBG(" tt_id: 0x%x \r\n", sc->tt_id);
|
||||
USB_LOG_DBG(" tt_port: 0x%x \r\n", sc->tt_port);
|
||||
USB_LOG_DBG("ctx[3]=0x%x\n", *((uint32_t*)ctx + 3));
|
||||
USB_LOG_DBG(" intr: 0x%x \r\n", sc->intr);
|
||||
USB_LOG_DBG(" address: 0x%x \r\n", sc->address);
|
||||
USB_LOG_DBG(" state: 0x%x \r\n", sc->state);
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump endpoint context
|
||||
*
|
||||
* @v ep Endpoint context
|
||||
*/
|
||||
void xhci_dump_ep_ctx(const struct xhci_endpoint_context *ep) {
|
||||
#if XHCI_DUMP_EP_CTX
|
||||
const uint8_t *ctx = (uint8_t *)ep;
|
||||
|
||||
USB_LOG_DBG("===== ep ctx ===== \r\n");
|
||||
USB_LOG_DBG("ctx[0]=0x%x\n", *((uint32_t*)ctx));
|
||||
USB_LOG_DBG(" ep_state: 0x%x \r\n", ep->state);
|
||||
USB_LOG_DBG(" mult: 0x%x \r\n", XHCI_EPCTX_MULT_GET(ep->stream));
|
||||
USB_LOG_DBG(" stream: 0x%x \r\n", XHCI_EPCTX_STREAM_GET(ep->stream));
|
||||
USB_LOG_DBG(" lsa: 0x%x \r\n", !!(XHCI_EPCTX_LSA & (ep->stream)));
|
||||
USB_LOG_DBG(" interval: 0x%x \r\n", ep->interval);
|
||||
USB_LOG_DBG(" esit_high: 0x%x \r\n", ep->esit_high);
|
||||
USB_LOG_DBG("ctx[1]=0x%x\n", *((uint32_t*)ctx + 1));
|
||||
USB_LOG_DBG(" cerr: 0x%x \r\n", XHCI_EPCTX_CERR_GET(ep->type));
|
||||
USB_LOG_DBG(" type: 0x%x \r\n", XHCI_EPCTX_TYPE_GET(ep->type));
|
||||
USB_LOG_DBG(" hid: 0x%x \r\n", !!(XHCI_EPCTX_HID & (ep->type)));
|
||||
USB_LOG_DBG(" burst: 0x%x \r\n", ep->burst);
|
||||
USB_LOG_DBG(" mtu: 0x%x \r\n", ep->mtu);
|
||||
USB_LOG_DBG("ctx[2]=0x%x\n", *((uint32_t*)ctx + 2));
|
||||
USB_LOG_DBG("ctx[3]=0x%x\n", *((uint32_t*)ctx + 3));
|
||||
USB_LOG_DBG(" dequeue: 0x%lx \r\n", ep->dequeue);
|
||||
USB_LOG_DBG(" dcs: 0x%lx \r\n", !!(XHCI_EPCTX_DCS & ep->dequeue));
|
||||
USB_LOG_DBG("ctx[4]=0x%x\n", *((uint32_t*)ctx + 4));
|
||||
USB_LOG_DBG(" trb_len: 0x%x \r\n", ep->trb_len);
|
||||
USB_LOG_DBG(" esit_low: 0x%x \r\n", ep->esit_low);
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump input context
|
||||
*
|
||||
* @v xhci XHCI device
|
||||
* @v endpoint Endpoint
|
||||
* @v input Input context
|
||||
*/
|
||||
void xhci_dump_input_ctx( struct xhci_host *xhci, const struct xhci_endpoint *endpoint, const void *input) {
|
||||
#if XHCI_DUMP_INPUT_CTX
|
||||
const struct xhci_control_context *control_ctx;
|
||||
const struct xhci_slot_context *slot_ctx;
|
||||
const struct xhci_endpoint_context *ep_ctx;
|
||||
|
||||
control_ctx = input;
|
||||
slot_ctx = ( input + xhci_input_context_offset ( xhci, XHCI_CTX_SLOT ));
|
||||
ep_ctx = ( input + xhci_input_context_offset ( xhci, endpoint->ctx ) );
|
||||
|
||||
USB_LOG_DBG("===input ctx====\n");
|
||||
USB_LOG_DBG("ctrl@%p=0x%x\n", control_ctx, *control_ctx);
|
||||
USB_LOG_DBG("add=0x%x\n", control_ctx->add);
|
||||
USB_LOG_DBG("del=0x%x\n", control_ctx->drop);
|
||||
|
||||
USB_LOG_DBG("slot@%p\n", slot_ctx);
|
||||
xhci_dump_slot_ctx(slot_ctx);
|
||||
|
||||
USB_LOG_DBG("ep-%d@%p\n", endpoint->ctx, ep_ctx);
|
||||
xhci_dump_ep_ctx(ep_ctx);
|
||||
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get next TRB in ring
|
||||
*
|
||||
* @v trbs TRB in ring
|
||||
* @v trb Next TRB
|
||||
*/
|
||||
static const union xhci_trb * xhci_get_next_trb(const union xhci_trb *trbs) {
|
||||
const struct xhci_trb_link *link = &(trbs->link);
|
||||
if (link->type == XHCI_TRB_LINK) {
|
||||
return (link->next) ? (const union xhci_trb *)(link->next) : NULL;
|
||||
} else {
|
||||
return trbs + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump TRB
|
||||
*
|
||||
* @v trbs TRB header
|
||||
* @v count Number of TRB to dump
|
||||
*/
|
||||
void xhci_dump_trbs(const union xhci_trb *trbs, unsigned int count) {
|
||||
#if XHCI_DUMP_TRB
|
||||
const union xhci_trb *cur;
|
||||
const struct xhci_trb_common *comm;
|
||||
const uint8_t *dword;
|
||||
|
||||
USB_LOG_DBG("===trbs ====\n");
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
cur = &(trbs[i]);
|
||||
dword = (const uint8_t *)cur;
|
||||
|
||||
comm = &(cur->common);
|
||||
USB_LOG_DBG("[0x%x-0x%x-0x%x-0x%x]\n",
|
||||
*((uint32_t *)dword), *((uint32_t *)dword + 1),
|
||||
*((uint32_t *)dword + 2), *((uint32_t *)dword + 3));
|
||||
if (XHCI_TRB_SETUP == comm->type) {
|
||||
const struct xhci_trb_setup *setup = (const struct xhci_trb_setup *)comm;
|
||||
|
||||
USB_LOG_DBG("setup trb\n");
|
||||
USB_LOG_DBG(" packet=0x%x\n", setup->packet);
|
||||
USB_LOG_DBG(" bmRequestType type=0x%x\n", setup->packet.bmRequestType);
|
||||
USB_LOG_DBG(" bRequest=0x%x\n", setup->packet.bRequest);
|
||||
USB_LOG_DBG(" wValue=0x%x\n", setup->packet.wValue);
|
||||
USB_LOG_DBG(" wIndex=0x%x\n", setup->packet.wIndex);
|
||||
USB_LOG_DBG(" wLength=0x%x\n", setup->packet.wLength);
|
||||
USB_LOG_DBG(" trb_trans_len=%d\n", setup->len);
|
||||
USB_LOG_DBG(" flags=0x%x\n", setup->flags);
|
||||
USB_LOG_DBG(" direction=%d\n", setup->direction);
|
||||
} else if (XHCI_TRB_DATA == comm->type) {
|
||||
const struct xhci_trb_data *data = (const struct xhci_trb_data *)comm;
|
||||
|
||||
USB_LOG_DBG("data trb......\n");
|
||||
USB_LOG_DBG(" data=0x%x\n", data->data);
|
||||
USB_LOG_DBG(" len=%d\n", data->len);
|
||||
USB_LOG_DBG(" direction=%d\n", data->direction);
|
||||
} else if (XHCI_TRB_STATUS == comm->type) {
|
||||
const struct xhci_trb_status *status = (const struct xhci_trb_status *)comm;
|
||||
|
||||
USB_LOG_DBG("status trb......\n");
|
||||
USB_LOG_DBG(" direction=%d\n", status->direction);
|
||||
}
|
||||
}
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *xhci_endpoint_xhci_type (unsigned int ep_xhci_type) {
|
||||
static const char *ep_names[] = {"not_valid", "isoc_out", "bulk_out",
|
||||
"intr_out", "ctrl", "isoc_in",
|
||||
"bulk_in", "intr_in"};
|
||||
unsigned int index = ep_xhci_type >> 3;
|
||||
if (index < sizeof(ep_names)/sizeof(ep_names[0])) {
|
||||
return ep_names[index];
|
||||
}
|
||||
|
||||
return "unkown";
|
||||
}
|
||||
|
||||
static const char *xhci_endpoint_type (unsigned int ep_type) {
|
||||
const char *ep_name = "unkown";
|
||||
|
||||
switch (ep_type)
|
||||
{
|
||||
case USB_ENDPOINT_TYPE_CONTROL:
|
||||
ep_name = "ctrl-ep";
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_ISOCHRONOUS:
|
||||
ep_name = "isoc-ep";
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_BULK:
|
||||
ep_name = "bulk-ep";
|
||||
break;
|
||||
case USB_ENDPOINT_TYPE_INTERRUPT:
|
||||
ep_name = "intr-ep";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ep_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump Endpoint
|
||||
*
|
||||
* @v ep Endpoint
|
||||
*/
|
||||
void xhci_dump_endpoint(const struct xhci_endpoint *ep) {
|
||||
#if XHCI_DUMP_ENDPOINT
|
||||
USB_LOG_DBG("===endpoint====\n");
|
||||
USB_LOG_DBG("xhci=0x%x\n", ep->xhci);
|
||||
USB_LOG_DBG("slot=0x%x\n", ep->slot);
|
||||
USB_LOG_DBG("address=0x%x\n", ep->address);
|
||||
USB_LOG_DBG("mtu=0x%x\n", ep->mtu);
|
||||
USB_LOG_DBG("burst=0x%x\n", ep->burst);
|
||||
USB_LOG_DBG("ctx=0x%x\n", ep->ctx);
|
||||
USB_LOG_DBG("ep_type=%s\n", xhci_endpoint_type(ep->ep_type));
|
||||
USB_LOG_DBG("xhci_type=%s\n", xhci_endpoint_xhci_type(ep->ctx_type));
|
||||
USB_LOG_DBG("interval=0x%x\n", ep->interval);
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump Port status
|
||||
*
|
||||
* @v port Port number
|
||||
* @v portsc Port status
|
||||
*/
|
||||
void xhci_dump_port_status(uint32_t port, uint32_t portsc) {
|
||||
#if XHCI_DUMP_PORT_STATUS
|
||||
USB_LOG_DBG("====port-%d====\n");
|
||||
USB_LOG_DBG("connect=%d \n", !!(XHCI_PORTSC_CCS & port));
|
||||
USB_LOG_DBG("enabled=%d \n", !!(XHCI_PORTSC_PED & port));
|
||||
USB_LOG_DBG("powered=%d \n", !!(XHCI_PORTSC_PP & port));
|
||||
USB_LOG_DBG("=====+++++++++===== \r\n");
|
||||
#endif
|
||||
}
|
||||
@@ -1,38 +1,31 @@
|
||||
/*
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* Copyright : (C) 2022 Phytium Information Technology, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
*
|
||||
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
|
||||
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
|
||||
* either version 1.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* See the Phytium Public License for more details.
|
||||
*
|
||||
*
|
||||
* FilePath: xhci_reg.h
|
||||
* Date: 2022-07-19 09:26:25
|
||||
* LastEditTime: 2022-07-19 09:26:25
|
||||
* Description: This files is for xhci register definition
|
||||
*
|
||||
* Modify History:
|
||||
* Description: This file is for xhci register definition.
|
||||
*
|
||||
* Modify History:
|
||||
* Ver Who Date Changes
|
||||
* ----- ------ -------- --------------------------------------
|
||||
* 1.0 zhugengyu 2022/9/19 init commit
|
||||
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
|
||||
*/
|
||||
#ifndef XHCI_REG_H
|
||||
#define XHCI_REG_H
|
||||
|
||||
/***************************** Include Files *********************************/
|
||||
#include "usbh_core.h"
|
||||
#ifndef XHCI_REG_H
|
||||
#define XHCI_REG_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/************************** Constant Definitions *****************************/
|
||||
#if defined(__aarch64__)
|
||||
#define BITS_PER_LONG 64U
|
||||
#define XHCI_AARCH64
|
||||
@@ -42,431 +35,356 @@ extern "C"
|
||||
#endif
|
||||
|
||||
#define XHCI_GENMASK(h, l) \
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||
(((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h))))
|
||||
|
||||
#define XHCI_GENMASK_ULL(h, l) \
|
||||
(((~0ULL) - (1ULL << (l)) + 1) & \
|
||||
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
|
||||
(((~0ULL) - (1ULL << (l)) + 1) & \
|
||||
(~0ULL >> (BITS_PER_LONG_LONG - 1 - (h))))
|
||||
|
||||
#define XHCI32_GET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) & XHCI_GENMASK(a, b)) >> b)
|
||||
#define XHCI32_SET_BITS(x, a, b) (uint32_t)((((uint32_t)(x)) << b) & XHCI_GENMASK(a, b))
|
||||
#define XHCI64_GET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) & XHCI_GENMASK_ULL(a, b)) >> b)
|
||||
#define XHCI64_SET_BITS(x, a, b) (uint64_t)((((uint64_t)(x)) << b) & XHCI_GENMASK_ULL(a, b))
|
||||
|
||||
/** @name Register Map
|
||||
/** Capability register length */
|
||||
#define XHCI_CAP_CAPLENGTH 0x00
|
||||
|
||||
/** Host controller interface version number */
|
||||
#define XHCI_CAP_HCIVERSION 0x02
|
||||
|
||||
/** Structural parameters 1 */
|
||||
#define XHCI_CAP_HCSPARAMS1 0x04
|
||||
|
||||
/** Number of device slots */
|
||||
#define XHCI_HCSPARAMS1_SLOTS(params) ( ( (params) >> 0 ) & 0xff )
|
||||
|
||||
/** Number of interrupters */
|
||||
#define XHCI_HCSPARAMS1_INTRS(params) ( ( (params) >> 8 ) & 0x3ff )
|
||||
|
||||
/** Number of ports */
|
||||
#define XHCI_HCSPARAMS1_PORTS(params) ( ( (params) >> 24 ) & 0xff )
|
||||
|
||||
/** Structural parameters 2 */
|
||||
#define XHCI_CAP_HCSPARAMS2 0x08
|
||||
|
||||
/** Number of page-sized scratchpad buffers */
|
||||
#define XHCI_HCSPARAMS2_SCRATCHPADS(params) \
|
||||
( ( ( (params) >> 16 ) & 0x3e0 ) | ( ( (params) >> 27 ) & 0x1f ) )
|
||||
|
||||
/** Capability parameters */
|
||||
#define XHCI_CAP_HCCPARAMS1 0x10
|
||||
|
||||
/** 64-bit addressing capability */
|
||||
#define XHCI_HCCPARAMS1_ADDR64(params) ( ( (params) >> 0 ) & 0x1 )
|
||||
|
||||
/** Context size shift */
|
||||
#define XHCI_HCCPARAMS1_CSZ_SHIFT(params) ( 5 + ( ( (params) >> 2 ) & 0x1 ) )
|
||||
|
||||
/** xHCI extended capabilities pointer */
|
||||
#define XHCI_HCCPARAMS1_XECP(params) ( ( ( (params) >> 16 ) & 0xffff ) << 2 )
|
||||
|
||||
/** Doorbell offset */
|
||||
#define XHCI_CAP_DBOFF 0x14
|
||||
|
||||
/** Runtime register space offset */
|
||||
#define XHCI_CAP_RTSOFF 0x18
|
||||
|
||||
/** xHCI extended capability ID */
|
||||
#define XHCI_XECP_ID(xecp) ( ( (xecp) >> 0 ) & 0xff )
|
||||
|
||||
/** Next xHCI extended capability pointer */
|
||||
#define XHCI_XECP_NEXT(xecp) ( ( ( (xecp) >> 8 ) & 0xff ) << 2 )
|
||||
|
||||
/** USB legacy support extended capability */
|
||||
#define XHCI_XECP_ID_LEGACY 1
|
||||
|
||||
/** USB legacy support BIOS owned semaphore */
|
||||
#define XHCI_USBLEGSUP_BIOS 0x02
|
||||
|
||||
/** USB legacy support BIOS ownership flag */
|
||||
#define XHCI_USBLEGSUP_BIOS_OWNED 0x01
|
||||
|
||||
/** USB legacy support OS owned semaphore */
|
||||
#define XHCI_USBLEGSUP_OS 0x03
|
||||
|
||||
/** USB legacy support OS ownership flag */
|
||||
#define XHCI_USBLEGSUP_OS_OWNED 0x01
|
||||
|
||||
/** USB legacy support control/status */
|
||||
#define XHCI_USBLEGSUP_CTLSTS 0x04
|
||||
|
||||
/** Supported protocol extended capability */
|
||||
#define XHCI_XECP_ID_SUPPORTED 2
|
||||
|
||||
/** Supported protocol revision */
|
||||
#define XHCI_SUPPORTED_REVISION 0x00
|
||||
|
||||
/** Supported protocol minor revision */
|
||||
#define XHCI_SUPPORTED_REVISION_VER(revision) ( ( (revision) >> 16 ) & 0xffff )
|
||||
|
||||
/** Supported protocol name */
|
||||
#define XHCI_SUPPORTED_NAME 0x04
|
||||
|
||||
/** Supported protocol ports */
|
||||
#define XHCI_SUPPORTED_PORTS 0x08
|
||||
|
||||
/** Supported protocol port offset */
|
||||
#define XHCI_SUPPORTED_PORTS_OFFSET(ports) ( ( (ports) >> 0 ) & 0xff )
|
||||
|
||||
/** Supported protocol port count */
|
||||
#define XHCI_SUPPORTED_PORTS_COUNT(ports) ( ( (ports) >> 8 ) & 0xff )
|
||||
|
||||
/** Supported protocol PSI count */
|
||||
#define XHCI_SUPPORTED_PORTS_PSIC(ports) ( ( (ports) >> 28 ) & 0x0f )
|
||||
|
||||
/** Supported protocol slot */
|
||||
#define XHCI_SUPPORTED_SLOT 0x0c
|
||||
|
||||
/** Supported protocol slot type */
|
||||
#define XHCI_SUPPORTED_SLOT_TYPE(slot) ( ( (slot) >> 0 ) & 0x1f )
|
||||
|
||||
/** Supported protocol PSI */
|
||||
#define XHCI_SUPPORTED_PSI(index) ( 0x10 + ( (index) * 4 ) )
|
||||
|
||||
/** Supported protocol PSI value */
|
||||
#define XHCI_SUPPORTED_PSI_VALUE(psi) ( ( (psi) >> 0 ) & 0x0f )
|
||||
|
||||
/** Supported protocol PSI mantissa */
|
||||
#define XHCI_SUPPORTED_PSI_MANTISSA(psi) ( ( (psi) >> 16 ) & 0xffff )
|
||||
|
||||
/** Supported protocol PSI exponent */
|
||||
#define XHCI_SUPPORTED_PSI_EXPONENT(psi) ( ( (psi) >> 4 ) & 0x03 )
|
||||
|
||||
/** Default PSI values */
|
||||
enum {
|
||||
/** Full speed (12Mbps) */
|
||||
XHCI_SPEED_FULL = 1,
|
||||
/** Low speed (1.5Mbps) */
|
||||
XHCI_SPEED_LOW = 2,
|
||||
/** High speed (480Mbps) */
|
||||
XHCI_SPEED_HIGH = 3,
|
||||
/** Super speed */
|
||||
XHCI_SPEED_SUPER = 4,
|
||||
};
|
||||
|
||||
/** USB command register */
|
||||
#define XHCI_OP_USBCMD 0x00
|
||||
|
||||
/** Run/stop */
|
||||
#define XHCI_USBCMD_RUN 0x00000001UL
|
||||
|
||||
/* Interrupter Enable (INTE) 1: enabled - RW */
|
||||
#define XHCI_USBCMD_INTE (1UL << 2)
|
||||
|
||||
/** Host controller reset */
|
||||
#define XHCI_USBCMD_HCRST 0x00000002UL
|
||||
|
||||
/** USB status register */
|
||||
#define XHCI_OP_USBSTS 0x04
|
||||
|
||||
/** Host controller halted */
|
||||
#define XHCI_USBSTS_HCH 0x00000001UL
|
||||
|
||||
/** Interrupt Pending (IP) */
|
||||
#define XHCI_USBSTS_EINT (1UL << 3)
|
||||
|
||||
/** Page size register */
|
||||
#define XHCI_OP_PAGESIZE 0x08
|
||||
|
||||
/** Page size */
|
||||
#define XHCI_PAGESIZE(pagesize) ( (pagesize) << 12 )
|
||||
|
||||
/** Device notifcation control register */
|
||||
#define XHCI_OP_DNCTRL 0x14
|
||||
|
||||
/** Command ring control register */
|
||||
#define XHCI_OP_CRCR 0x18
|
||||
|
||||
/** Command ring cycle state */
|
||||
#define XHCI_CRCR_RCS 0x00000001UL
|
||||
|
||||
/** Command abort */
|
||||
#define XHCI_CRCR_CA 0x00000004UL
|
||||
|
||||
/** Command ring running */
|
||||
#define XHCI_CRCR_CRR 0x00000008UL
|
||||
|
||||
/** Device context base address array pointer */
|
||||
#define XHCI_OP_DCBAAP 0x30
|
||||
|
||||
/** Configure register */
|
||||
#define XHCI_OP_CONFIG 0x38
|
||||
|
||||
/** Maximum device slots enabled */
|
||||
#define XHCI_CONFIG_MAX_SLOTS_EN(slots) ( (slots) << 0 )
|
||||
|
||||
/** Maximum device slots enabled mask */
|
||||
#define XHCI_CONFIG_MAX_SLOTS_EN_MASK \
|
||||
XHCI_CONFIG_MAX_SLOTS_EN ( 0xff )
|
||||
|
||||
/** Port status and control register */
|
||||
#define XHCI_OP_PORTSC(port) ( 0x400 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/** Current connect status */
|
||||
#define XHCI_PORTSC_CCS 0x00000001UL
|
||||
|
||||
/** Port enabled */
|
||||
#define XHCI_PORTSC_PED 0x00000002UL
|
||||
|
||||
#define XHCI_PORTSC_OCA (1 << 3)
|
||||
|
||||
/** Port reset */
|
||||
#define XHCI_PORTSC_PR 0x00000010UL
|
||||
|
||||
/** Port link state */
|
||||
#define XHCI_PORTSC_PLS(pls) ( (pls) << 5 )
|
||||
|
||||
/** U0 state */
|
||||
#define XHCI_PORTSC_PLS_U0 XHCI_PORTSC_PLS ( 0 )
|
||||
|
||||
/** Disabled port link state */
|
||||
#define XHCI_PORTSC_PLS_DISABLED XHCI_PORTSC_PLS ( 4 )
|
||||
|
||||
/** RxDetect port link state */
|
||||
#define XHCI_PORTSC_PLS_RXDETECT XHCI_PORTSC_PLS ( 5 )
|
||||
|
||||
/** Polling state */
|
||||
#define XHCI_PORTSC_PLS_POLLING XHCI_PORTSC_PLS ( 7 )
|
||||
|
||||
/** Port link state mask */
|
||||
#define XHCI_PORTSC_PLS_MASK XHCI_PORTSC_PLS ( 0xf )
|
||||
|
||||
/** Port power */
|
||||
#define XHCI_PORTSC_PP 0x00000200UL
|
||||
|
||||
/** Time to delay after enabling power to a port */
|
||||
#define XHCI_PORT_POWER_DELAY_MS 20
|
||||
|
||||
/** Port speed ID value */
|
||||
#define XHCI_PORTSC_PSIV(portsc) ( ( (portsc) >> 10 ) & 0xf )
|
||||
|
||||
/** Port indicator control */
|
||||
#define XHCI_PORTSC_PIC(indicators) ( (indicators) << 14 )
|
||||
|
||||
/** Port indicator control mask */
|
||||
#define XHCI_PORTSC_PIC_MASK XHCI_PORTSC_PIC ( 3 )
|
||||
|
||||
/** Port link state write strobe */
|
||||
#define XHCI_PORTSC_LWS 0x00010000UL
|
||||
|
||||
/** Time to delay after writing the port link state */
|
||||
#define XHCI_LINK_STATE_DELAY_MS 100
|
||||
|
||||
/** Connect status change */
|
||||
#define XHCI_PORTSC_CSC (1 << 17)
|
||||
|
||||
/** Port enabled/disabled change */
|
||||
#define XHCI_PORTSC_PEC (1 << 18)
|
||||
|
||||
/** Warm port reset change */
|
||||
#define XHCI_PORTSC_WRC (1 << 19)
|
||||
|
||||
/** Over-current change */
|
||||
#define XHCI_PORTSC_OCC (1 << 20)
|
||||
|
||||
/** Port reset change */
|
||||
#define XHCI_PORTSC_PRC (1 << 21)
|
||||
|
||||
/** Port link state change */
|
||||
#define XHCI_PORTSC_PLC (1 << 22)
|
||||
|
||||
/** Port config error change */
|
||||
#define XHCI_PORTSC_CEC (1 << 23)
|
||||
|
||||
/* Cold Attach Status 1: Far-end Receiver Terminations were detected */
|
||||
#define XHCI_PORTSC_CAS (1 << 24)
|
||||
|
||||
/* Wake on Connect Enable 1: enable port to be sensitive to device connects */
|
||||
#define XHCI_PORTSC_WCE (1 << 25)
|
||||
|
||||
/* Wake on Disconnect Enable 1: enable port to be sensitive to device disconnects */
|
||||
#define XHCI_PORTSC_WDE (1 << 26)
|
||||
|
||||
/* Wake on Over-current Enable 1: enable port to be sensitive to over-current conditions */
|
||||
#define XHCI_PORTSC_WOE (1 << 27)
|
||||
|
||||
/* Device Removable, 0: Device is removable. 1: Device is non-removable */
|
||||
#define XHCI_PORTSC_DR (1 << 30)
|
||||
|
||||
/* Warm Port Reset 1: follow Warm Reset sequence */
|
||||
#define XHCI_PORTSC_WPR (1 << 31)
|
||||
|
||||
/** Port status change mask */
|
||||
#define XHCI_PORTSC_CHANGE \
|
||||
( XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_WRC | \
|
||||
XHCI_PORTSC_OCC | XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | \
|
||||
XHCI_PORTSC_CEC )
|
||||
|
||||
#define XHCI_PORTSC_RW_MASK (XHCI_PORTSC_PR | XHCI_PORTSC_PLS_MASK | XHCI_PORTSC_PP \
|
||||
| XHCI_PORTSC_PIC_MASK | XHCI_PORTSC_LWS | XHCI_PORTSC_WCE \
|
||||
| XHCI_PORTSC_WDE | XHCI_PORTSC_WOE)
|
||||
|
||||
/** Port status and control bits which should be preserved
|
||||
*
|
||||
* Register offsets from the base address of an XHCI device.
|
||||
* @{
|
||||
* The port status and control register is a horrendous mix of
|
||||
* differing semantics. Some bits are written to only when a separate
|
||||
* write strobe bit is set. Some bits should be preserved when
|
||||
* modifying other bits. Some bits will be cleared if written back as
|
||||
* a one. Most excitingly, the "port enabled" bit has the semantics
|
||||
* that 1=enabled, 0=disabled, yet writing a 1 will disable the port.
|
||||
*/
|
||||
#define XHCI_REG_CAP_CAPLENGTH 0x00 /* specify the limits, restrictions and capabilities */
|
||||
#define XHCI_REG_CAP_HCIVERSION 0x02 /* Interface Version Number */
|
||||
#define XHCI_REG_CAP_HCS1 0x04 /* Host Controller Structural Parameters 1 */
|
||||
#define XHCI_REG_CAP_HCS2 0x08 /* Host Controller Structural Parameters 2 */
|
||||
#define XHCI_REG_CAP_HCS3 0x0C /* Host Controller Structural Parameters 3 */
|
||||
#define XHCI_REG_CAP_HCC 0x10 /* Capability Parameters 1 */
|
||||
#define XHCI_REG_CAP_DBOFF 0x14 /* Doorbell Offset Register */
|
||||
#define XHCI_REG_CAP_RTSOFF 0x18 /* Runtime Register Space Offset Register */
|
||||
#define XHCI_PORTSC_PRESERVE ( XHCI_PORTSC_PP | XHCI_PORTSC_PIC_MASK )
|
||||
|
||||
/***************** Host Controller Operational Registers ***********************/
|
||||
#define XHCI_REG_OP_USBCMD 0x00 /* USB Command Register */
|
||||
#define XHCI_REG_OP_USBSTS 0x04 /* USB Status Register */
|
||||
#define XHCI_REG_OP_PAGESIZE 0x08 /* Page Size Register */
|
||||
#define XHCI_REG_OP_DNCTRL 0x14 /* Device Notification Control Register */
|
||||
#define XHCI_REG_OP_CRCR 0x18 /* Command Ring Control Register */
|
||||
#define XHCI_REG_OP_DCBAAP 0x30 /* Device Context Base Address Array Pointer Register */
|
||||
#define XHCI_REG_OP_CONFIG 0x38 /* Configure Register */
|
||||
/** Port power management status and control register */
|
||||
#define XHCI_OP_PORTPMSC(port) ( 0x404 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/* Port Status and Ctrl Register : OP Base + (400h + (10h * (n–1))) 'n' is port num */
|
||||
#define XHCI_REG_OP_PORTS_BASE 0x400 /* Port Status and Control Register Base */
|
||||
#define XHCI_REG_OP_PORTS_SIZE 0x10 /* Size of one Port SC Register */
|
||||
#define XHCI_REG_OP_PORTS_OFF(port, off) ((port) * XHCI_REG_OP_PORTS_SIZE + offset)
|
||||
/** Port link info register */
|
||||
#define XHCI_OP_PORTLI(port) ( 0x408 - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
#define XHCI_REG_OP_PORTS_PORTSC 0x00 /* Port Status and Control Register */
|
||||
#define XHCI_REG_OP_PORTS_PORTPMSC 0x04 /* USB3 Port Power Management Status and Control Register */
|
||||
#define XHCI_REG_OP_PORTS_PORTLI 0x08 /* Port Link Info Register */
|
||||
/** Port hardware link power management control register */
|
||||
#define XHCI_OP_PORTHLPMC(port) ( 0x40c - 0x10 + ( (port) << 4 ) )
|
||||
|
||||
/***************** Host Controller Runtime Registers ***********************/
|
||||
#define XHCI_REG_RT_MFINDEX 0x00 /* Microframe Index */
|
||||
#define XHCI_REG_RT_IR0 0x20 /* Interrupter Register Set 0 */
|
||||
#define XHCI_REG_RT_IR1023 0x8000 /* Interrupter Register Set 1023 */
|
||||
/* Doorbell registers are 32 bits in length */
|
||||
#define XHCI_REG_DB_SIZE 4
|
||||
|
||||
/* Interrupter Register Set : RT Base + 020h + (32 * Interrupter) */
|
||||
#define XHCI_REG_RT_IR_IMAN 0x00 /* Interrupter Management Register */
|
||||
#define XHCI_REG_RT_IR_IMOD 0x04 /* Interrupter Moderation Register */
|
||||
#define XHCI_REG_RT_IR_ERSTSZ 0x08 /* Event Ring Segment Table Size Register */
|
||||
#define XHCI_REG_RT_IR_ERSTBA 0x10 /* Event Ring Segment Table Base Address Register */
|
||||
#define XHCI_REG_RT_IR_ERDP 0x18 /* Event Ring Dequeue Pointer Register */
|
||||
#define XHCI_REG_RT_IR_SIZE 0x20 /* Size of one IR Register */
|
||||
/** Interrupter Management Register */
|
||||
#define XHCI_RUN_IR_IMAN(intr) ( 0x20 + ( (intr) << 5 ) )
|
||||
|
||||
/***************** Doorbell Register ***********************/
|
||||
#define XHCI_REG_DB_SIZE 4 /* Doorbell registers are 32 bits in length */
|
||||
/* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
|
||||
#define XHCI_RUN_IR_IMAN_IP (1 << 0)
|
||||
|
||||
/***************** eXtensible Host Controller Capability Registers ***********************/
|
||||
/* Interrupt Enable, 1: capable of generating an interrupt. */
|
||||
#define XHCI_RUN_IR_IMAN_IE (1 << 1)
|
||||
|
||||
/** @name XHCI_REG_CAP_HCS1 Register
|
||||
/** Interrupter Moderation Register */
|
||||
#define XHCI_RUN_IR_IMOD(intr) ( 0x24 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring segment table size register */
|
||||
#define XHCI_RUN_ERSTSZ(intr) ( 0x28 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring segment table base address register */
|
||||
#define XHCI_RUN_ERSTBA(intr) ( 0x30 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event ring dequeue pointer register */
|
||||
#define XHCI_RUN_ERDP(intr) ( 0x38 + ( (intr) << 5 ) )
|
||||
|
||||
/** Event Handler Busy */
|
||||
#define XHCI_RUN_ERDP_EHB (1 << 3)
|
||||
|
||||
/** Minimum alignment required for data structures
|
||||
*
|
||||
* With the exception of the scratchpad buffer pages (which are
|
||||
* page-aligned), data structures used by xHCI generally require from
|
||||
* 16 to 64 byte alignment and must not cross an (xHCI) page boundary.
|
||||
* We simplify this requirement by aligning each structure on its own
|
||||
* size, with a minimum of a 64 byte alignment.
|
||||
*/
|
||||
#define XHCI_REG_CAP_HCS1_MAX_SLOTS_GET(x) XHCI32_GET_BITS(x, 7, 0) /* Number of Device Slots (MaxSlots) */
|
||||
#define XHCI_REG_CAP_HCS1_MAX_INTRS_GET(x) XHCI32_GET_BITS(x, 18, 8) /* Number of Interrupters (MaxIntrs) */
|
||||
#define XHCI_REG_CAP_HCS1_MAX_PORTS_GET(x) XHCI32_GET_BITS(x, 31, 24) /* Number of Ports (MaxPorts) */
|
||||
#define XHCI_MIN_ALIGN 64
|
||||
|
||||
/** @name XHCI_REG_CAP_HCS2 Register
|
||||
*/
|
||||
#define XHCI_REG_CAP_HCS2_IST_GET(x) XHCI32_GET_BITS(x, 3, 0) /* Isochronous Scheduling Threshold (IST) */
|
||||
#define XHCI_REG_CAP_HCS2_ERST_MAX_GET(x) XHCI32_GET_BITS(x, 7, 4) /* Event Ring Segment Table Max (ERST Max) */
|
||||
#define XHCI_REG_CAP_HCS2_SPR (1 << 26) /* Scratchpad Restore (SPR) */
|
||||
#define XHCI_REG_CAP_HCS2_MAX_SCRATCHPAD_BUFS_GET(x) XHCI32_GET_BITS(x, 25, 21) | XHCI32_GET_BITS(x, 31, 27) /* Max Scratchpad Buffers (Max Scratchpad Bufs) */
|
||||
|
||||
/** @name XHCI_REG_CAP_HCS3 Register
|
||||
*/
|
||||
#define XHCI_REG_CAP_HCS3_U1_DEV_EXIT_LATENCY_GET(x) XHCI32_GET_BITS(x, 7, 0) /* U1 Device Exit Latency */
|
||||
#define XHCI_REG_CAP_HCS3_U2_DEV_EXIT_LATENCY_GET(x) XHCI32_GET_BITS(x, 31, 16) /* U2 Device Exit Latency */
|
||||
|
||||
/** @name XHCI_REG_CAP_HCC Register
|
||||
*/
|
||||
#define XHCI_REG_CAP_HCC_AC64 (1 << 0) /* 64-bit Addressing Capabilitya 1: 64-bit */
|
||||
#define XHCI_REG_CAP_HCC_BNC (1 << 1) /* BW Negotiation Capability (BNC) 1: support */
|
||||
#define XHCI_REG_CAP_HCC_CSZ (1 << 2) /* Context Size (CSZ) 1: 64 byte context data */
|
||||
#define XHCI_REG_CAP_HCC_PPC (1 << 3) /* Port Power Control (PPC) 1: support */
|
||||
#define XHCI_REG_CAP_HCC_PIND (1 << 4) /* Port Indicators (PIND) 1: support */
|
||||
#define XHCI_REG_CAP_HCC_LHRC (1 << 5) /* Light HC Reset Capability (LHRC) 1: support */
|
||||
#define XHCI_REG_CAP_HCC_LTC (1 << 6) /* Latency Tolerance Messaging Capability (LTC) */
|
||||
#define XHCI_REG_CAP_HCC_NSS (1 << 7) /* No Secondary SID Support (NSS) */
|
||||
#define XHCI_REG_CAP_HCC_MAX_PSA_SIZE_GET(x) XHCI32_GET_BITS(x, 15, 12) /* Maximum Primary Stream Array Size (MaxPSASize) */
|
||||
#define XHCI_REG_CAP_HCC_XECP_GET(x) XHCI32_GET_BITS(x, 31, 16) /* xHCI Extended Capabilities Pointer (xECP) */
|
||||
|
||||
/** @name XHCI_REG_CAP_DBOFF Register
|
||||
*/
|
||||
#define XHCI_REG_CAP_DBOFF_GET(x) ((x) & XHCI_GENMASK(31, 2)) /* 32-byte offset of the Doorbell Array base address from the Base */
|
||||
|
||||
/** @name XHCI_REG_CAP_RTSOFF Register
|
||||
*/
|
||||
#define XHCI_REG_CAP_RTSOFF_GET(x) ((x) & XHCI_GENMASK(31, 5)) /* 32-byte offset of the xHCI Runtime Registers */
|
||||
|
||||
|
||||
/***************** Host Controller Operational Registers ***********************/
|
||||
|
||||
/** @name XHCI_REG_OP_USBCMD Register
|
||||
*/
|
||||
#define XHCI_REG_OP_USBCMD_RUN_STOP (1 << 0) /* Run/Stop (R/S) 1: RUN, 0: STOP - RW */
|
||||
#define XHCI_REG_OP_USBCMD_HCRST (1 << 1) /* Host Controller Reset (HCRST) 1: RESET - RW */
|
||||
#define XHCI_REG_OP_USBCMD_INTE (1 << 2) /* Interrupter Enable (INTE) 1: enabled - RW */
|
||||
#define XHCI_REG_OP_USBCMD_HSEE (1 << 3) /* Host System Error Enable (HSEE) - RW */
|
||||
#define XHCI_REG_OP_USBCMD_LHCRST (1 << 7) /* Light Host Controller Reset (LHCRST) - RW */
|
||||
#define XHCI_REG_OP_USBCMD_CSS (1 << 8) /* Controller Save State (CSS) - RW */
|
||||
#define XHCI_REG_OP_USBCMD_CRS (1 << 9) /* Controller Restore State (CRS) - RW */
|
||||
#define XHCI_REG_OP_USBCMD_EWE (1 << 10) /* Enable Wrap Event (EWE) - RW */
|
||||
#define XHCI_REG_OP_USBCMD_EU3S (1 << 11) /* Enable U3 MFINDEX Stop (EU3S) - RW */
|
||||
|
||||
/** @name XHCI_REG_OP_USBSTS Register
|
||||
*/
|
||||
#define XHCI_REG_OP_USBSTS_HCH (1 << 0) /* 1: Stopped executing */
|
||||
#define XHCI_REG_OP_USBSTS_HSE (1 << 2) /* 1: Serious error detected */
|
||||
#define XHCI_REG_OP_USBSTS_EINT (1 << 3) /* 1: Interrupt Pending (IP) */
|
||||
#define XHCI_REG_OP_USBSTS_PCD (1 << 4) /* 1: Port Change Detect */
|
||||
#define XHCI_REG_OP_USBSTS_SSS (1 << 8) /* remain 1 while the xHC saves its internal state */
|
||||
#define XHCI_REG_OP_USBSTS_RSS (1 << 9) /* remain 1 while the xHC restores its internal state */
|
||||
#define XHCI_REG_OP_USBSTS_SRE (1 << 10) /* if error occurs during a Save or Restore operation this bit shall be set to ‘1’. */
|
||||
#define XHCI_REG_OP_USBSTS_CNR (1 << 11) /* 1: Controller Not Ready */
|
||||
#define XHCI_REG_OP_USBSTS_HCE (1 << 12) /* 1: Internal xHC error condition */
|
||||
#define XHCI_REG_OP_USBSTS_PRSRV_MASK ((1 << 1) | 0xffffe000) /* Rsvd bits */
|
||||
|
||||
|
||||
/** @name XHCI_REG_OP_PAGESIZE Register
|
||||
*/
|
||||
/* This xHC supports a page size of 2^(n+12) if bit n is Set */
|
||||
#define XHCI_REG_OP_PAGESIZE_4K (1 << 0) /* if bit 0 is Set, the xHC supports 4k byte page sizes */
|
||||
|
||||
/** @name XHCI_REG_OP_CRCR Register
|
||||
*/
|
||||
#define XHCI_REG_OP_CRCR_RCS (1 << 0) /* Ring Cycle State, value of the xHC Consumer Cycle State (CCS) flag */
|
||||
#define XHCI_REG_OP_CRCR_CS (1 << 1) /* Command Stop, 1 */
|
||||
#define XHCI_REG_OP_CRCR_CA (1 << 2) /* Command Abort, 1 */
|
||||
#define XHCI_REG_OP_CRCR_CRR (1 << 3) /* Command Ring Running */
|
||||
#define XHCI_REG_OP_CRCR_CR_PTR_MASK XHCI_GENMASK_ULL(63, 6) /* Command Ring Pointer, Dequeue Ptr of Command Ring */
|
||||
|
||||
/** @name XHCI_REG_OP_DCBAAP Register
|
||||
*/
|
||||
#define XHCI_REG_OP_DCBAAP_MASK XHCI_GENMASK_ULL(63, 6) /* bit[31:6] Ptr of DCBAA */
|
||||
|
||||
/** @name XHCI_REG_OP_CONFIG Register
|
||||
*/
|
||||
#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_MASK XHCI_GENMASK(7, 0) /* Max Device Slots Enabled (MaxSlotsEn) – RW */
|
||||
#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_SET(x) XHCI32_SET_BITS(x, 7, 0) /* bit[7:0] Max Device Slots Enabled */
|
||||
#define XHCI_REG_OP_CONFIG_MAX_SLOTS_EN_GET(x) XHCI32_GET_BITS(x, 7, 0)
|
||||
|
||||
/** @name XHCI_REG_OP_PORTS_PORTSC Register
|
||||
*/
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_CCS (1 << 0) /* Current Connect Status (CCS) – ROS */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PED (1 << 1) /* Port Enabled/Disabled (PED) – RW1CS */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_OCA (1 << 3) /* Over-current Active (OCA) – RO */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PR (1 << 4) /* Port Reset (PR) – RW1S */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLS_GET(x) XHCI32_GET_BITS(x, 8, 5) /* Port Link State (PLS) – RWS */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) XHCI32_SET_BITS(x, 8, 5)
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLS_MASK XHCI_GENMASK(8, 5)
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLS(x) (x << 5)
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) XHCI32_SET_BITS(x, 8, 5)
|
||||
|
||||
enum PLSStatus{
|
||||
PLS_U0 = 0,
|
||||
PLS_U1 = 1,
|
||||
PLS_U2 = 2,
|
||||
PLS_U3 = 3,
|
||||
PLS_DISABLED = 4,
|
||||
PLS_RX_DETECT = 5,
|
||||
PLS_INACTIVE = 6,
|
||||
PLS_POLLING = 7,
|
||||
PLS_RECOVERY = 8,
|
||||
PLS_HOT_RESET = 9,
|
||||
PLS_COMPILANCE_MODE = 10,
|
||||
PLS_TEST_MODE = 11,
|
||||
PLS_RESUME = 15,
|
||||
}; /* Port status type */
|
||||
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PP (1 << 9) /* Port Power (PP) – RWS */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(x) XHCI32_GET_BITS(x, 13, 10) /* Port Speed (Port Speed) – ROS */
|
||||
|
||||
/* Protocol Speed ID (PSI) */
|
||||
#define XHCI_PORT_SPEED_UNKOWN 0U
|
||||
#define XHCI_PORT_SPEED_FULL 1U
|
||||
#define XHCI_PORT_SPEED_LOW 2U
|
||||
#define XHCI_PORT_SPEED_HIGH 3U
|
||||
#define XHCI_PORT_SPEED_SUPER 4U
|
||||
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PIC_SET(x) XHCI32_SET_BITS(x, 15, 14)
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PIC_MASK XHCI_GENMASK(15, 14)
|
||||
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_LWS (1 << 16) /* Port Link State Write Strobe (LWS) */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_CSC (1 << 17) /* Connect Status Change (CSC) */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PEC (1 << 18) /* Port Enabled/Disabled Change (PEC) 1: clear PED */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_WRC (1 << 19) /* Warm Port Reset Change 1: Warm Reset complete */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_OCC (1 << 20) /* Over-current Change 1: Over-current Active */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PRC (1 << 21) /* Port Reset Change 1: Transition of Port Reset */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_PLC (1 << 22) /* Port Link State Change 1: PLS transition */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_CEC (1 << 23) /* Port Config Error Change 1: Port Config Error detected */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_CAS (1 << 24) /* Cold Attach Status 1: Far-end Receiver Terminations were detected */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_WCE (1 << 25) /* Wake on Connect Enable 1: enable port to be sensitive to device connects */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_WDE (1 << 26) /* Wake on Disconnect Enable 1: enable port to be sensitive to device disconnects */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_WOE (1 << 27) /* Wake on Over-current Enable 1: enable port to be sensitive to over-current conditions */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_DR (1 << 30) /* Device Removable, 0: Device is removable. 1: Device is non-removable */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_WPR (1 << 31) /* Warm Port Reset 1: follow Warm Reset sequence */
|
||||
#define XHCI_REG_OP_PORTS_PORTSC_RW_MASK (XHCI_REG_OP_PORTS_PORTSC_PR | XHCI_REG_OP_PORTS_PORTSC_PLS_MASK | XHCI_REG_OP_PORTS_PORTSC_PP \
|
||||
| XHCI_REG_OP_PORTS_PORTSC_PIC_MASK | XHCI_REG_OP_PORTS_PORTSC_LWS | XHCI_REG_OP_PORTS_PORTSC_WCE \
|
||||
| XHCI_REG_OP_PORTS_PORTSC_WDE | XHCI_REG_OP_PORTS_PORTSC_WOE)
|
||||
|
||||
|
||||
/***************** Host Controller Runtime Registers ***********************/
|
||||
|
||||
/** @name XHCI_REG_RT_IR_IMAN Register
|
||||
*/
|
||||
#define XHCI_REG_RT_IR_IMAN_IP (1 << 0) /* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
|
||||
#define XHCI_REG_RT_IR_IMAN_IE (1 << 1) /* Interrupt Enable, 1: capable of generating an interrupt. */
|
||||
|
||||
/** @name XHCI_REG_RT_IR_IMOD Register
|
||||
*/
|
||||
#define XHCI_REG_RT_IR_IMOD_IMODI_MASK XHCI_GENMASK(15, 0) /* bit[15:0] Interrupt Moderation Interval default 4000 ==> 1ms */
|
||||
#define XHCI_REG_RT_IR_IMOD_IMODC_MASK XHCI_GENMASK(31, 16) /* bit[31:16] Interrupt Moderation Counter(Down counter) */
|
||||
|
||||
/** @name XHCI_REG_RT_IR_ERSTSZ Register
|
||||
*/
|
||||
#define XHCI_REG_RT_IR_ERSTSZ_MASK XHCI_GENMASK(15, 0) /* bit[15:0] the number of valid Event Ring Segment Table entries */
|
||||
|
||||
/** @name XHCI_REG_RT_IR_ERSTBA Register
|
||||
*/
|
||||
#define XHCI_REG_RT_IR_ERSTBA_MASK XHCI_GENMASK_ULL(63, 6) /* Event Ring Segment Table Base Address */
|
||||
|
||||
/** @name XHCI_REG_RT_IR_ERDP Register
|
||||
*/
|
||||
#define XHCI_REG_RT_IR_ERDP_DESI_MASK XHCI_GENMASK_ULL(2, 0) /* bit[2:0] Dequeue ERST Segment Index */
|
||||
#define XHCI_REG_RT_IR_ERDP_EHB (1 << 3) /* Event Handler Busy */
|
||||
#define XHCI_REG_RT_IR_ERDP_MASK XHCI_GENMASK_ULL(63, 4) /* Event Ring Dequeue Pointer */
|
||||
|
||||
/***************** Doorbell Register ***********************/
|
||||
#define XHCI_REG_DB_TARGET_HC_COMMAND 0 /* Host Controller Doorbell (0) Command Doorbell */
|
||||
#define XHCI_REG_DB_TARGET_EP0 1 /* Device Context Doorbells Control EP 0 Enqueue Pointer Update */
|
||||
#define XHCI_REG_DB_TARGET_EP1_OUT 2 /* EP 1 OUT Enqueue Pointer Update */
|
||||
#define XHCI_REG_DB_TARGET_EP1_IN 3 /* EP 1 IN Enqueue Pointer Update */
|
||||
#define XHCI_REG_DB_TARGET_EP15_OUT 30 /* EP 15 OUT Enqueue Pointer Update */
|
||||
#define XHCI_REG_DB_TARGET_EP15_IN 31 /* EP 15 IN Enqueue Pointer Update */
|
||||
|
||||
/***************** xHCI Extended Capabilities Registers ***********************/
|
||||
#define XHCI_REG_EXT_CAP_USBSPCF_OFFSET 0x0
|
||||
#define XHCI_REG_EXT_CAP_CAP_ID_GET(x) XHCI32_GET_BITS(x, 7, 0)
|
||||
#define XHCI_REG_EXT_NEXT_CAP_PTR_GET(x) XHCI32_GET_BITS(x, 15, 8)
|
||||
/* refer to 'Table 138: xHCI Extended Capability Codes' for more details */
|
||||
enum
|
||||
{
|
||||
XHCI_EXT_CAP_ID_USB_LEGACY_SUPPORT = 1,
|
||||
XHCI_EXT_CAP_ID_SUPPORT_PROTOCOL = 2,
|
||||
XHCI_EXT_CAP_ID_EXTEND_POWER_MANAGEMENT = 3,
|
||||
XHCI_EXT_CAP_ID_IO_VIRTUALIZATION = 4,
|
||||
XHCI_EXT_CAP_ID_MESSAGE_INTERRUPT = 5,
|
||||
XHCI_EXT_CAP_ID_LOCAL_MEMORY = 6,
|
||||
XHCI_EXT_CAP_ID_USB_DEBUG_CAPABILITY = 10,
|
||||
XHCI_EXT_CAP_ID_EXT_MESSAGE_INTERRUPT = 17,
|
||||
|
||||
XHCI_EXT_CAP_ID_VENDOR_DEFINED_MIN = 192,
|
||||
XHCI_EXT_CAP_ID_VENDOR_DEFINED_MAX = 255
|
||||
};
|
||||
|
||||
/* xHCI Supported Protocol Capability */
|
||||
#define XHCI_REG_EXT_CAP_USBSPCFDEF_OFFSET 0x4
|
||||
|
||||
#define XHCI_USBSPCF_MINOR_REVERSION_GET(x) XHCI32_GET_BITS(x, 23, 16)
|
||||
#define XHCI_USBSPCF_MAJOR_REVERSION_GET(x) XHCI32_GET_BITS(x, 31, 24)
|
||||
|
||||
#define XHCI_USBSPCFDEF_NAME_STRING_GET(x) XHCI32_GET_BITS(x, 31, 0) /* four ASCII characters may be defined */
|
||||
#define XHCI_USBSPCFDEF_NAME_STRING_USB 0x20425355 /* ASCII = "USB" */
|
||||
|
||||
#define XHCI_REG_EXT_CAP_USBSPCFDEF2_OFFSET 0x8
|
||||
#define XHCI_USBSPCFDEF2_COMPATIBLE_PORT_OFF_GET(x) XHCI32_GET_BITS(x, 7, 0)
|
||||
#define XHCI_USBSPCFDEF2_COMPATIBLE_PORT_CNT_GET(x) XHCI32_GET_BITS(x, 15, 8)
|
||||
#define XHCI_USBSPCFDEF2_PROTOCOL_DEFINED_GET(x) XHCI32_GET_BITS(x, 27, 16)
|
||||
|
||||
/* trb bit definitions */
|
||||
|
||||
/* configuration */
|
||||
#define XHCI_RING_ITEMS 16U
|
||||
#define XHCI_ALIGMENT 64U
|
||||
#define XHCI_RING_SIZE (XHCI_RING_ITEMS*sizeof(struct xhci_trb))
|
||||
|
||||
#define TRB_C (1<<0)
|
||||
#define TRB_TYPE_SHIFT 10
|
||||
#define TRB_TYPE_MASK 0x3f
|
||||
#define TRB_TYPE_GET(val) XHCI32_GET_BITS(val, 15, 10)
|
||||
#define TRB_TYPE_SET(t) XHCI32_SET_BITS(t, 15, 10)
|
||||
|
||||
#define TRB_EV_ED (1<<2)
|
||||
|
||||
#define TRB_TR_ENT (1<<1)
|
||||
#define TRB_TR_ISP (1<<2)
|
||||
#define TRB_TR_NS (1<<3)
|
||||
#define TRB_TR_CH (1<<4)
|
||||
#define TRB_TR_IOC (1<<5)
|
||||
#define TRB_TR_IDT (1<<6)
|
||||
#define TRB_TR_TBC_SHIFT 7
|
||||
#define TRB_TR_TBC_MASK 0x3
|
||||
#define TRB_TR_BEI (1<<9)
|
||||
#define TRB_TR_TLBPC_SHIFT 16
|
||||
#define TRB_TR_TLBPC_MASK 0xf
|
||||
#define TRB_TR_FRAMEID_SHIFT 20
|
||||
#define TRB_TR_FRAMEID_MASK 0x7ff
|
||||
#define TRB_TR_SIA (1<<31)
|
||||
#define TRB_TR_TRANS_LEN_SET(len) XHCI32_SET_BITS(len, 23, 0)
|
||||
#define TRB_TR_TRANS_LEN_MASK XHCI_GENMASK(23, 0)
|
||||
|
||||
#define TRB_TR_DIR (1<<16)
|
||||
#define TRB_TR_TYPE_SET(t) XHCI32_SET_BITS(t, 17, 16)
|
||||
#define TRB_TR_NO_DATA 0U
|
||||
#define TRB_TR_OUT_DATA 2U
|
||||
#define TRB_TR_IN_DATA 3U
|
||||
|
||||
#define TRB_CC_GET(val) XHCI32_GET_BITS(val, 31, 24)
|
||||
#define TRB_PORT_ID_GET(val) XHCI32_GET_BITS(val, 31, 24)
|
||||
|
||||
|
||||
#define TRB_CR_SLOTID_SHIFT 24
|
||||
#define TRB_CR_SLOTID_MASK 0xff
|
||||
#define TRB_CR_SLOTID_SET(id) XHCI32_SET_BITS(id, 31, 24)
|
||||
#define TRB_CR_SLOTID_GET(val) XHCI32_GET_BITS(val, 31, 24)
|
||||
|
||||
#define TRB_CR_EPID_SHIFT 16
|
||||
#define TRB_CR_EPID_MASK 0x1f
|
||||
#define TRB_CR_EPID_SET(id) XHCI32_SET_BITS(id, 20, 16)
|
||||
#define TRB_CR_EPID_GET(field) XHCI32_GET_BITS(field, 20, 16)
|
||||
|
||||
#define TRB_CR_BSR (1<<9)
|
||||
#define TRB_CR_DC (1<<9)
|
||||
|
||||
#define TRB_LK_TC (1<<1)
|
||||
|
||||
#define TRB_INTR_SHIFT 22
|
||||
#define TRB_INTR_MASK 0x3ff
|
||||
#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK)
|
||||
|
||||
/************************** Type Definitions *********************************/
|
||||
enum TRBType {
|
||||
TRB_RESERVED = 0,
|
||||
TR_NORMAL,
|
||||
TR_SETUP,
|
||||
TR_DATA,
|
||||
TR_STATUS,
|
||||
TR_ISOCH,
|
||||
TR_LINK,
|
||||
TR_EVDATA,
|
||||
TR_NOOP,
|
||||
CR_ENABLE_SLOT,
|
||||
CR_DISABLE_SLOT,
|
||||
CR_ADDRESS_DEVICE,
|
||||
CR_CONFIGURE_ENDPOINT,
|
||||
CR_EVALUATE_CONTEXT,
|
||||
CR_RESET_ENDPOINT,
|
||||
CR_STOP_ENDPOINT,
|
||||
CR_SET_TR_DEQUEUE,
|
||||
CR_RESET_DEVICE,
|
||||
CR_FORCE_EVENT,
|
||||
CR_NEGOTIATE_BW,
|
||||
CR_SET_LATENCY_TOLERANCE,
|
||||
CR_GET_PORT_BANDWIDTH,
|
||||
CR_FORCE_HEADER,
|
||||
CR_NOOP,
|
||||
ER_TRANSFER_COMPLETE = 32,
|
||||
ER_COMMAND_COMPLETE,
|
||||
ER_PORT_STATUS_CHANGE,
|
||||
ER_BANDWIDTH_REQUEST,
|
||||
ER_DOORBELL,
|
||||
ER_HOST_CONTROLLER,
|
||||
ER_DEVICE_NOTIFICATION,
|
||||
ER_MFINDEX_WRAP,
|
||||
};
|
||||
|
||||
enum TRBCCode {
|
||||
CC_DISCONNECTED = -2,
|
||||
CC_TIMEOUT = -1,
|
||||
CC_INVALID = 0,
|
||||
CC_SUCCESS,
|
||||
CC_DATA_BUFFER_ERROR,
|
||||
CC_BABBLE_DETECTED,
|
||||
CC_USB_TRANSACTION_ERROR,
|
||||
CC_TRB_ERROR,
|
||||
CC_STALL_ERROR,
|
||||
CC_RESOURCE_ERROR,
|
||||
CC_BANDWIDTH_ERROR,
|
||||
CC_NO_SLOTS_ERROR,
|
||||
CC_INVALID_STREAM_TYPE_ERROR,
|
||||
CC_SLOT_NOT_ENABLED_ERROR,
|
||||
CC_EP_NOT_ENABLED_ERROR,
|
||||
CC_SHORT_PACKET,
|
||||
CC_RING_UNDERRUN,
|
||||
CC_RING_OVERRUN,
|
||||
CC_VF_ER_FULL,
|
||||
CC_PARAMETER_ERROR,
|
||||
CC_BANDWIDTH_OVERRUN,
|
||||
CC_CONTEXT_STATE_ERROR,
|
||||
CC_NO_PING_RESPONSE_ERROR,
|
||||
CC_EVENT_RING_FULL_ERROR,
|
||||
CC_INCOMPATIBLE_DEVICE_ERROR,
|
||||
CC_MISSED_SERVICE_ERROR,
|
||||
CC_COMMAND_RING_STOPPED,
|
||||
CC_COMMAND_ABORTED,
|
||||
CC_STOPPED,
|
||||
CC_STOPPED_LENGTH_INVALID,
|
||||
CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR = 29,
|
||||
CC_ISOCH_BUFFER_OVERRUN = 31,
|
||||
CC_EVENT_LOST_ERROR,
|
||||
CC_UNDEFINED_ERROR,
|
||||
CC_INVALID_STREAM_ID_ERROR,
|
||||
CC_SECONDARY_BANDWIDTH_ERROR,
|
||||
CC_SPLIT_TRANSACTION_ERROR
|
||||
};
|
||||
|
||||
/***************** Macros (Inline Functions) Definitions *********************/
|
||||
/*
|
||||
* xhci_ring structs are allocated with XHCI_RING_SIZE alignment,
|
||||
* then we can get it from a trb pointer (provided by evt ring).
|
||||
*/
|
||||
#define XHCI_RING(_trb) \
|
||||
((struct xhci_ring*)((unsigned long)(_trb) & ~(XHCI_RING_SIZE-1)))
|
||||
/** Maximum transfer size */
|
||||
#define XHCI_MTU 65536
|
||||
|
||||
/** Read/Write Data Barrier for ARM */
|
||||
#define BARRIER() __asm__ __volatile__("": : :"memory")
|
||||
|
||||
#ifdef XHCI_AARCH64
|
||||
@@ -475,55 +393,107 @@ enum TRBCCode {
|
||||
#define DSB() __asm__ __volatile__("dsb": : : "memory")
|
||||
#endif
|
||||
|
||||
/************************** Function Prototypes ******************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
static inline void writeq(unsigned long addr, uint64_t val) {
|
||||
BARRIER();
|
||||
*(volatile uint64_t *)addr = val;
|
||||
}
|
||||
|
||||
static inline void writel(unsigned long addr, uint32_t val) {
|
||||
BARRIER();
|
||||
*(volatile uint32_t *)addr = val;
|
||||
}
|
||||
|
||||
static inline void writew(unsigned long addr, uint16_t val) {
|
||||
BARRIER();
|
||||
*(volatile uint16_t *)addr = val;
|
||||
}
|
||||
|
||||
static inline void writeb(unsigned long addr, uint8_t val) {
|
||||
BARRIER();
|
||||
*(volatile uint8_t *)addr = val;
|
||||
}
|
||||
|
||||
static inline uint64_t readq(unsigned long addr) {
|
||||
uint64_t val = *(volatile const uint64_t *)addr;
|
||||
/**
|
||||
* Read byte from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint8_t readb(void *io_addr ) {
|
||||
uint8_t val = *(volatile const uint8_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint32_t readl(unsigned long addr) {
|
||||
uint32_t val = *(volatile const uint32_t *)addr;
|
||||
/**
|
||||
* Read 16-bit word from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint16_t readw(void * io_addr ) {
|
||||
uint16_t val = *(volatile const uint16_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint16_t readw(unsigned long addr) {
|
||||
uint16_t val = *(volatile const uint16_t *)addr;
|
||||
/**
|
||||
* Read 32-bit dword from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint32_t readl(void * io_addr ) {
|
||||
uint32_t val = *(volatile const uint32_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline uint8_t readb(unsigned long addr) {
|
||||
uint8_t val = *(volatile const uint8_t *)addr;
|
||||
/**
|
||||
* Read 64-bit qword from memory-mapped device
|
||||
*
|
||||
* @v io_addr I/O address
|
||||
* @ret data Value read
|
||||
*/
|
||||
static inline uint64_t readq(void * io_addr ) {
|
||||
uint64_t val = *(volatile const uint64_t *)io_addr;
|
||||
BARRIER();
|
||||
return val;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
/**
|
||||
* Write byte to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writeb(uint8_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint8_t *)io_addr = data;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/**
|
||||
* Write 16-bit word to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writew(uint16_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint16_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 32-bit dword to memory-mapped device
|
||||
*
|
||||
* @v data Value to writed
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writel(uint32_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint32_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 64-bit qword to memory-mapped device
|
||||
*
|
||||
* @v data Value to write
|
||||
* @v io_addr I/O address
|
||||
*/
|
||||
static inline void writeq(uint64_t data, void * io_addr ) {
|
||||
BARRIER();
|
||||
*(volatile uint64_t *)io_addr = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Byte-order converter for ARM-Little-End
|
||||
*/
|
||||
#define CPU_TO_LE64(x) ((uint64_t)(x))
|
||||
#define LE64_to_CPU(x) ((uint64_t)(x))
|
||||
#define CPU_TO_LE32(x) ((uint32_t)(x))
|
||||
#define LE32_TO_CPU(x) ((uint32_t)(x))
|
||||
#define CPU_TO_LE16(x) ((uint16_t)(x))
|
||||
#define LE16_TO_CPU(x) ((uint16_t)(x))
|
||||
|
||||
|
||||
#endif /* XHCI_REG_H */
|
||||
Reference in New Issue
Block a user