remove old version

This commit is contained in:
sakumisu 2024-06-07 10:29:44 +08:00
parent b1660f743f
commit 6fd87902b5
6 changed files with 0 additions and 5002 deletions

View File

@ -1,505 +0,0 @@
/*
* 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: usb_hc_xhci.c
* Date: 2022-09-19 17:24:36
* LastEditTime: 2022-09-19 17:24:36
* Description:  This file is for xhci function implementation.
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 zhugengyu 2022/9/19 init commit
* 1.1 zhugengyu 2022/10/9 add dumpers and fix command abort
* 2.0 zhugengyu 2023/3/29 support usb3.0 device attached at roothub
*/
/***************************** Include Files *********************************/
#include "usbh_hub.h"
#include "xhci.h"
/************************** Constant Definitions *****************************/
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
/*****************************************************************************/
__WEAK void usb_hc_low_level_init(void)
{
}
__WEAK void *usb_hc_malloc(size_t size)
{
return NULL;
}
__WEAK void *usb_hc_malloc_align(size_t align, size_t size)
{
return NULL;
}
__WEAK void usb_hc_free()
{
}
/* one may get xhci register base address by PCIe bus emuration */
__WEAK unsigned long usb_hc_get_register_base(void)
{
return 0U;
}
/**
* Get USB root hub port
*
* @v hport Hub port of USB device
* @ret port Root hub port
*/
extern struct usbh_hubport *usbh_root_hub_port(struct usbh_hubport *hport);
static struct xhci_host xhci_host;
/* xhci hardware init */
int usb_hc_init()
{
int rc = 0;
struct xhci_host *xhci = &(xhci_host);
size_t flag = usb_osal_enter_critical_section(); /* no interrupt when init hc */
usb_hc_low_level_init(); /* set gic and memp */
memset(xhci, 0, sizeof(*xhci));
xhci->id = CONFIG_USBHOST_XHCI_ID;
if (rc = xhci_probe(xhci, usb_hc_get_register_base()) != 0) {
goto err_open;
}
if (rc = xhci_open(xhci) != 0 ) {
goto err_open;
}
err_open:
usb_osal_leave_critical_section(flag);
return rc;
}
int usbh_roothub_control(struct usb_setup_packet *setup, uint8_t *buf)
{
uint8_t nports;
uint8_t port;
uint32_t portsc;
uint32_t status;
int ret = 0;
struct xhci_host *xhci = &xhci_host;
nports = CONFIG_USBHOST_MAX_RHPORTS;
port = setup->wIndex;
/*
bmRequestType bit[4:0], define whether the request is directed to the device (0000b),
specific interface (00001b), endpoint (00010b), or other element (00011b)
bRequest, identifies the request
wValue, pass the request-specific info to the device
*/
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) /* request is directed to device */
{
switch (setup->bRequest)
{
case HUB_REQUEST_CLEAR_FEATURE: /* disable the feature */
switch (setup->wValue)
{
case HUB_FEATURE_HUB_C_LOCALPOWER:
USB_LOG_ERR("HUB_FEATURE_HUB_C_LOCALPOWER not implmented.\n");
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
USB_LOG_ERR("HUB_FEATURE_HUB_C_OVERCURRENT not implmented.\n");
break;
default:
return -EPIPE;
}
break;
case HUB_REQUEST_SET_FEATURE: /* set a value reported in the hub status */
switch (setup->wValue)
{
case HUB_FEATURE_HUB_C_LOCALPOWER:
USB_LOG_ERR("HUB_FEATURE_HUB_C_LOCALPOWER not implmented.\n");
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
USB_LOG_ERR("HUB_FEATURE_HUB_C_OVERCURRENT not implmented.\n");
break;
default:
return -EPIPE;
}
break;
case HUB_REQUEST_GET_DESCRIPTOR:
USB_LOG_ERR("HUB_REQUEST_GET_DESCRIPTOR not implmented.\n");
break;
case HUB_REQUEST_GET_STATUS:
USB_ASSERT(buf);
memset(buf, 0, 4);
break;
default:
break;
}
}
else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER)
{
switch (setup->bRequest)
{
case HUB_REQUEST_CLEAR_FEATURE:
if (!port || port > nports)
{
return -EPIPE;
}
portsc = readl ( xhci->op + XHCI_OP_PORTSC ( port ) );
switch (setup->wValue)
{
case HUB_PORT_FEATURE_ENABLE:
break;
case HUB_PORT_FEATURE_SUSPEND:
case HUB_PORT_FEATURE_C_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_C_CONNECTION:
portsc |= XHCI_PORTSC_CSC;
break;
case HUB_PORT_FEATURE_C_ENABLE:
portsc |= XHCI_PORTSC_PEC;
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
break;
case HUB_PORT_FEATURE_C_RESET:
break;
default:
return -EPIPE;
}
uint32_t pclear = portsc & XHCI_PORTSC_RW_MASK;
/* clear port status */
writel(pclear, xhci->op + XHCI_OP_PORTSC ( port ));
break;
case HUB_REQUEST_SET_FEATURE:
if (!port || port > nports)
{
return -EPIPE;
}
switch (setup->wValue)
{
case HUB_PORT_FEATURE_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_RESET:
ret = xhci_port_enable(xhci, port);
break;
default:
return -EPIPE;
}
break;
case HUB_REQUEST_GET_STATUS:
if (!port || port > nports)
{
return -EPIPE;
}
portsc = readl ( xhci->op + XHCI_OP_PORTSC ( port ) );
status = 0;
if (portsc & XHCI_PORTSC_CSC)
{
/* Port connection status changed */
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
/* always clear all the status change bits */
uint32_t temp = portsc & ( XHCI_PORTSC_PRESERVE | XHCI_PORTSC_CHANGE );
writel ( temp, xhci->op + XHCI_OP_PORTSC ( port ) );
}
if (portsc & XHCI_PORTSC_PEC)
{
/* Port enabled status changed */
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
}
if (portsc & XHCI_PORTSC_OCC)
{
/* Port status changed due to over-current */
status |= (1 << HUB_PORT_FEATURE_C_OVER_CURREN);
}
if (portsc & XHCI_PORTSC_CCS)
{
/* Port connected */
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
}
if (portsc & XHCI_PORTSC_PED)
{
/* Port enabled */
status |= (1 << HUB_PORT_FEATURE_ENABLE);
const unsigned int speed = xhci_root_speed(xhci, port);
USB_LOG_DBG("Port-%d speed = %d \r\n", port, speed);
if (speed == USB_SPEED_LOW)
{
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
}
else if (speed == USB_SPEED_HIGH)
{
status |= (1 << HUB_PORT_FEATURE_HIGHSPEED);
}
/* else is full-speed */
}
if (portsc & XHCI_PORTSC_OCA)
{
/* Over-current condition */
status |= (1 << HUB_PORT_FEATURE_OVERCURRENT);
}
if (portsc & XHCI_PORTSC_PR)
{
/* Reset is in progress */
status |= (1 << HUB_PORT_FEATURE_RESET);
}
if (portsc & XHCI_PORTSC_PP)
{
/* Port is not power off */
status |= (1 << HUB_PORT_FEATURE_POWER);
}
memcpy(buf, &status, 4);
break;
default:
break;
}
}
return 0;
}
uint8_t usbh_get_port_speed(struct usbh_hub *hub, const uint8_t port)
{
USB_ASSERT(hub);
struct xhci_host *xhci = &(xhci_host);
if (hub->is_roothub) {
return xhci_root_speed(xhci, port);
} else {
struct usbh_hubport *roothub_port = usbh_root_hub_port(&(hub->child[port]));
/* TODO, hanlde TT for low-speed device on high-speed hub, but it doesn't matter, since
we haven't well handle hub yet */
USB_ASSERT(roothub_port);
return xhci_root_speed(xhci, roothub_port->port);
}
}
int usbh_ep_pipe_reconfigure(usbh_pipe_t pipe, uint8_t dev_addr, uint8_t mtu, uint8_t speed)
{
struct xhci_endpoint *ppipe = (struct xhci_endpoint *)pipe;
size_t old_mtu = ppipe->mtu;
int rc = 0;
if (mtu != old_mtu) {
ppipe->mtu = mtu;
rc = xhci_endpoint_mtu(ppipe);
}
return rc;
}
int usbh_pipe_alloc(usbh_pipe_t *pipe, const struct usbh_endpoint_cfg *ep_cfg)
{
int rc = 0;
int slot_id = 0;
struct xhci_host *xhci = &xhci_host;
struct usbh_hubport *hport = ep_cfg->hport;
struct xhci_endpoint *ppipe = usb_align(XHCI_RING_SIZE, sizeof(struct xhci_endpoint));
struct xhci_slot *slot;
if (NULL == ppipe) {
return -ENOMEM;
}
memset(ppipe, 0, sizeof(struct xhci_endpoint));
ppipe->waitsem = usb_osal_sem_create(0);
ppipe->waiter = false;
ppipe->urb = NULL;
ppipe->hport = hport;
ppipe->address = ep_cfg->ep_addr;
ppipe->mtu = ep_cfg->ep_mps;
ppipe->interval = ep_cfg->ep_interval;
ppipe->ep_type = ep_cfg->ep_type;
ppipe->burst = 0U;
if (ppipe->address == 0) { /* if try to allocate ctrl ep, open device first */
USB_LOG_DBG("allocate device for port-%d \r\n", hport->port);
rc = xhci_device_open(xhci, ppipe, &slot_id);
if (rc) {
goto failed;
}
slot = xhci->slot[slot_id];
USB_ASSERT(slot);
rc = xhci_ctrl_endpoint_open(xhci, slot, ppipe);
if (rc) {
goto failed;
}
rc = xhci_device_address(xhci, slot, ppipe);
if (rc) {
goto failed;
}
} else {
slot_id = hport->dev_addr;
slot = xhci->slot[slot_id];
rc = xhci_work_endpoint_open(xhci, slot, ppipe);
if (rc) {
goto failed;
}
}
*pipe = (usbh_pipe_t)ppipe;
return rc;
failed:
usb_free(ppipe);
*pipe = NULL;
return rc;
}
int usbh_get_xhci_devaddr(usbh_pipe_t *pipe)
{
struct xhci_endpoint *ppipe = (struct xhci_endpoint *)pipe;
USB_ASSERT(ppipe && (ppipe->slot));
return ppipe->slot->id;
}
int usbh_pipe_free(usbh_pipe_t pipe)
{
int ret = 0;
struct xhci_endpoint *ppipe = (struct xhci_endpoint *)pipe;
if (!ppipe) {
return -EINVAL;
}
struct usbh_urb *urb = ppipe->urb;
if (urb) {
usbh_kill_urb(urb);
}
size_t flags = usb_osal_enter_critical_section();
xhci_endpoint_close(ppipe);
usb_osal_leave_critical_section(flags);
return 0;
}
int usbh_submit_urb(struct usbh_urb *urb)
{
int ret = 0;
if (!urb || !urb->pipe) {
return -EINVAL;
}
struct xhci_endpoint *ppipe = (struct xhci_endpoint *)urb->pipe;
struct xhci_host *xhci = ppipe->xhci;
struct usb_setup_packet *setup = urb->setup;
size_t flags = usb_osal_enter_critical_section();
urb->errorcode = -EBUSY;
urb->actual_length = 0U;
ppipe->urb = urb;
ppipe->timeout = urb->timeout;
if (ppipe->timeout > 0) {
ppipe->waiter = true;
} else {
ppipe->waiter = false;
}
usb_osal_leave_critical_section(flags);
switch (ppipe->ep_type) {
case USB_ENDPOINT_TYPE_CONTROL:
USB_ASSERT(setup);
if (setup->bRequest == USB_REQUEST_SET_ADDRESS) {
/* Set address command sent during xhci_alloc_pipe. */
goto skip_req;
}
USB_LOG_DBG("%s request-%d.\n", __func__, setup->bRequest);
xhci_endpoint_message(ppipe, setup, urb->transfer_buffer, urb->transfer_buffer_length);
break;
case USB_ENDPOINT_TYPE_INTERRUPT:
case USB_ENDPOINT_TYPE_BULK:
xhci_endpoint_stream(ppipe, urb->transfer_buffer, urb->transfer_buffer_length);
break;
default:
USB_ASSERT(0U);
break;
}
/* wait all ring handled by xHc */
int cc = xhci_event_wait(xhci, ppipe, &ppipe->reqs);
if ((cc != XHCI_CMPLT_SUCCESS) &&
!((cc == XHCI_CMPLT_TIMEOUT) && (ppipe->ep_type == USB_ENDPOINT_TYPE_INTERRUPT)))
{
/* ignore transfer timeout for interrupt type */
USB_LOG_ERR("%s: xfer failed (cc %d).\n", __func__, cc);
ret = -1;
urb->errorcode = cc;
goto errout_timeout;
}
skip_req:
errout_timeout:
/* Timeout will run here */
usbh_kill_urb(urb);
return ret;
}
int usbh_kill_urb(struct usbh_urb *urb)
{
return 0;
}
void USBH_IRQHandler(void *param)
{
struct xhci_host *xhci = &xhci_host;
struct xhci_endpoint *work_pipe = NULL;
USB_ASSERT(xhci);
uint32_t usbsts;
uint32_t runtime;
/* clear interrupt status */
usbsts = readl ( xhci->op + XHCI_OP_USBSTS );
usbsts |= XHCI_USBSTS_EINT;
writel(usbsts, xhci->op + XHCI_OP_USBSTS);
/* ack interrupt */
runtime = readl(xhci->run + XHCI_RUN_IR_IMAN ( 0 ));
runtime |= XHCI_RUN_IR_IMAN_IP;
writel (runtime, xhci->run + XHCI_RUN_IR_IMAN ( 0 ));
work_pipe = xhci_event_process(xhci);
}

View File

@ -1,38 +0,0 @@
/*
* 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: usb_hc_xhci.h
* Date: 2022-07-19 09:26:25
* LastEditTime: 2022-07-19 09:26:25
* 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"
/************************** Constant Definitions *****************************/
/************************** Variable Definitions *****************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/

File diff suppressed because it is too large Load Diff

View File

@ -1,940 +0,0 @@
/*
* 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 */

View File

@ -1,353 +0,0 @@
/*
* 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
}

View File

@ -1,499 +0,0 @@
/*
* 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_reg.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_REG_H
#define XHCI_REG_H
#if defined(__aarch64__)
#define BITS_PER_LONG 64U
#define XHCI_AARCH64
#else
#define BITS_PER_LONG 32U
#define XHCI_AARCH32
#endif
#define XHCI_GENMASK(h, l) \
(((~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))))
#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))
/** 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
*
* 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_PORTSC_PRESERVE ( XHCI_PORTSC_PP | XHCI_PORTSC_PIC_MASK )
/** Port power management status and control register */
#define XHCI_OP_PORTPMSC(port) ( 0x404 - 0x10 + ( (port) << 4 ) )
/** Port link info register */
#define XHCI_OP_PORTLI(port) ( 0x408 - 0x10 + ( (port) << 4 ) )
/** Port hardware link power management control register */
#define XHCI_OP_PORTHLPMC(port) ( 0x40c - 0x10 + ( (port) << 4 ) )
/* Doorbell registers are 32 bits in length */
#define XHCI_REG_DB_SIZE 4
/** Interrupter Management Register */
#define XHCI_RUN_IR_IMAN(intr) ( 0x20 + ( (intr) << 5 ) )
/* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
#define XHCI_RUN_IR_IMAN_IP (1 << 0)
/* Interrupt Enable, 1: capable of generating an interrupt. */
#define XHCI_RUN_IR_IMAN_IE (1 << 1)
/** 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_MIN_ALIGN 64
/** Maximum transfer size */
#define XHCI_MTU 65536
/** Read/Write Data Barrier for ARM */
#define BARRIER() __asm__ __volatile__("": : :"memory")
#ifdef XHCI_AARCH64
#define DSB() __asm__ __volatile__("dsb sy": : : "memory")
#else
#define DSB() __asm__ __volatile__("dsb": : : "memory")
#endif
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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;
}
/**
* 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 */