588 lines
27 KiB
C
588 lines
27 KiB
C
/*
|
||
* 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: fxhci_hw.h
|
||
* Date: 2022-02-11 13:33:12
|
||
* LastEditTime: 2022-02-18 09:13:47
|
||
* Description: This files is for definition of XHCI hardware register interface
|
||
*
|
||
* Modify History:
|
||
* Ver Who Date Changes
|
||
* ----- ------ -------- --------------------------------------
|
||
* 1.0 zhugengyu 2022/2/7 init commit
|
||
*/
|
||
|
||
#ifndef FXHCI_HW_H
|
||
#define FXHCI_HW_H
|
||
|
||
/***************************** Include Files *********************************/
|
||
#include "fio.h"
|
||
#include "fassert.h"
|
||
#include "fkernel.h"
|
||
|
||
#ifdef __cplusplus
|
||
extern "C"
|
||
{
|
||
#endif
|
||
|
||
/************************** Constant Definitions *****************************/
|
||
/** @name Register Map
|
||
*
|
||
* Register offsets from the base address of an SD device.
|
||
* @{
|
||
*/
|
||
/***************** eXtensible Host Controller Capability Registers ***********************/
|
||
#define FXHCI_REG_CAP_CAPLENGTH 0x00 /* specify the limits, restrictions and capabilities */
|
||
#define FXHCI_REG_CAP_HCIVERSION 0x02 /* Interface Version Number */
|
||
#define FXHCI_REG_CAP_HCSPARAMS1 0x04 /* Host Controller Structural Parameters 1 */
|
||
#define FXHCI_REG_CAP_HCSPARAMS2 0x08 /* Host Controller Structural Parameters 2 */
|
||
#define FXHCI_REG_CAP_HCSPARAMS3 0x0C /* Host Controller Structural Parameters 3 */
|
||
#define FXHCI_REG_CAP_HCCPARAMS 0x10 /* Capability Parameters 1 */
|
||
#define FXHCI_REG_CAP_DBOFF 0x14 /* Doorbell Offset Register */
|
||
#define FXHCI_REG_CAP_RTSOFF 0x18 /* Runtime Register Space Offset Register */
|
||
|
||
/***************** Host Controller Operational Registers ***********************/
|
||
#define FXHCI_REG_OP_USBCMD 0x00 /* USB Command Register */
|
||
#define FXHCI_REG_OP_USBSTS 0x04 /* USB Status Register */
|
||
#define FXHCI_REG_OP_PAGESIZE 0x08 /* Page Size Register */
|
||
#define FXHCI_REG_OP_DNCTRL 0x14 /* Device Notification Control Register */
|
||
#define FXHCI_REG_OP_CRCR 0x18 /* Command Ring Control Register */
|
||
#define FXHCI_REG_OP_DCBAAP 0x30 /* Device Context Base Address Array Pointer Register */
|
||
#define FXHCI_REG_OP_CONFIG 0x38 /* Configure Register */
|
||
|
||
/* Port Status and Ctrl Register : OP Base + (400h + (10h * (n–1))) 'n' is port num */
|
||
#define FXHCI_REG_OP_PORTS_BASE 0x400 /* Port Status and Control Register Base */
|
||
#define FXHCI_REG_OP_PORTS_SIZE 0x10 /* Size of one Port SC Register */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC 0x00 /* Port Status and Control Register */
|
||
#define FXHCI_REG_OP_PORTS_PORTPMSC 0x04 /* USB3 Port Power Management Status and Control Register */
|
||
#define FXHCI_REG_OP_PORTS_PORTLI 0x08 /* Port Link Info Register */
|
||
|
||
/***************** Host Controller Runtime Registers ***********************/
|
||
#define FXHCI_REG_RT_MFINDEX 0x00 /* Microframe Index */
|
||
#define FXHCI_REG_RT_IR0 0x20 /* Interrupter Register Set 0 */
|
||
#define FXHCI_REG_RT_IR1023 0x8000 /* Interrupter Register Set 1023 */
|
||
|
||
/* Interrupter Register Set : RT Base + 020h + (32 * Interrupter) */
|
||
#define FXHCI_REG_RT_IR_SIZE 0x20 /* Size of one IR Register */
|
||
#define FXHCI_REG_RT_IR_IMAN 0x00 /* Interrupter Management Register */
|
||
#define FXHCI_REG_RT_IR_IMOD 0x04 /* Interrupter Moderation Register */
|
||
#define FXHCI_REG_RT_IR_ERSTSZ 0x08 /* Event Ring Segment Table Size Register */
|
||
#define FXHCI_REG_RT_IR_ERSTBA 0x10 /* Event Ring Segment Table Base Address Register */
|
||
#define FXHCI_REG_RT_IR_ERDP 0x18 /* Event Ring Dequeue Pointer Register */
|
||
|
||
/***************** Doorbell Register ***********************/
|
||
#define FXHCI_REG_DB_SIZE 4 /* Doorbell registers are 32 bits in length */
|
||
|
||
/***************** eXtensible Host Controller Capability Registers ***********************/
|
||
|
||
/** @name FXHCI_REG_CAP_HCSPARAMS1 Register
|
||
*/
|
||
#define FXHCI_REG_CAP_HCSPARAMS1_MAX_SLOTS_GET(x) FUSB_REG32_GET_BITS(x, 7, 0) /* Number of Device Slots (MaxSlots) */
|
||
#define FXHCI_REG_CAP_HCSPARAMS1_MAX_INTRS_GET(x) FUSB_REG32_GET_BITS(x, 18, 8) /* Number of Interrupters (MaxIntrs) */
|
||
#define FXHCI_REG_CAP_HCSPARAMS1_MAX_PORTS_GET(x) FUSB_REG32_GET_BITS(x, 31, 24) /* Number of Ports (MaxPorts) */
|
||
|
||
/** @name FXHCI_REG_CAP_HCSPARAMS2 Register
|
||
*/
|
||
#define FXHCI_REG_CAP_HCSPARAMS2_IST_GET(x) FUSB_REG32_GET_BITS(x, 3, 0) /* Isochronous Scheduling Threshold (IST) */
|
||
#define FXHCI_REG_CAP_HCSPARAMS2_ERST_MAX_GET(x) FUSB_REG32_GET_BITS(x, 7, 4) /* Event Ring Segment Table Max (ERST Max) */
|
||
#define FXHCI_REG_CAP_HCSPARAMS2_SPR (1 << 26) /* Scratchpad Restore (SPR) */
|
||
#define FXHCI_REG_CAP_HCSPARAMS2_MAX_SCRATCHPAD_BUFS_GET(x) FUSB_REG32_GET_BITS(x, 31, 27) /* Max Scratchpad Buffers (Max Scratchpad Bufs) */
|
||
|
||
/** @name FXHCI_REG_CAP_HCSPARAMS3 Register
|
||
*/
|
||
#define FXHCI_REG_CAP_HCSPARAMS3_U1_DEV_EXIT_LATENCY_GET(x) FUSB_REG32_GET_BITS(x, 7, 0) /* U1 Device Exit Latency */
|
||
#define FXHCI_REG_CAP_HCSPARAMS3_U2_DEV_EXIT_LATENCY_GET(x) FUSB_REG32_GET_BITS(x, 31, 16) /* U2 Device Exit Latency */
|
||
|
||
/** @name FXHCI_REG_CAP_HCCPARAMS Register
|
||
*/
|
||
#define FXHCI_REG_CAP_HCCPARAMS_AC64 (1 << 0) /* 64-bit Addressing Capabilitya 1: 64-bit */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_BNC (1 << 1) /* BW Negotiation Capability (BNC) 1: support */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_CSZ (1 << 2) /* Context Size (CSZ) 1: 64 byte context data */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_PPC (1 << 3) /* Port Power Control (PPC) 1: support */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_PIND (1 << 4) /* Port Indicators (PIND) 1: support */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_LHRC (1 << 5) /* Light HC Reset Capability (LHRC) 1: support */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_LTC (1 << 6) /* Latency Tolerance Messaging Capability (LTC) */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_NSS (1 << 7) /* No Secondary SID Support (NSS) */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_MAX_PSA_SIZE_GET(x) FUSB_REG32_GET_BITS(x, 15, 12) /* Maximum Primary Stream Array Size (MaxPSASize) */
|
||
#define FXHCI_REG_CAP_HCCPARAMS_XECP_GET(x) FUSB_REG32_GET_BITS(x, 31, 16) /* xHCI Extended Capabilities Pointer (xECP) */
|
||
|
||
/** @name FXHCI_REG_CAP_DBOFF Register
|
||
*/
|
||
#define FXHCI_REG_CAP_DBOFF_GET(x) ((x) & GENMASK(31, 2)) /* 32-byte offset of the Doorbell Array base address from the Base */
|
||
|
||
/** @name FXHCI_REG_CAP_RTSOFF Register
|
||
*/
|
||
#define FXHCI_REG_CAP_RTSOFF_GET(x) ((x) & GENMASK(31, 5)) /* 32-byte offset of the xHCI Runtime Registers */
|
||
|
||
/***************** Host Controller Operational Registers ***********************/
|
||
|
||
/** @name FXHCI_REG_OP_USBCMD Register
|
||
*/
|
||
#define FXHCI_REG_OP_USBCMD_RUN_STOP (1 << 0) /* Run/Stop (R/S) 1: RUN, 0: STOP - RW */
|
||
#define FXHCI_REG_OP_USBCMD_HCRST (1 << 1) /* Host Controller Reset (HCRST) 1: RESET - RW */
|
||
#define FXHCI_REG_OP_USBCMD_INTE (1 << 2) /* Interrupter Enable (INTE) 1: enabled - RW */
|
||
#define FXHCI_REG_OP_USBCMD_HSEE (1 << 3) /* Host System Error Enable (HSEE) - RW */
|
||
#define FXHCI_REG_OP_USBCMD_LHCRST (1 << 7) /* Light Host Controller Reset (LHCRST) - RW */
|
||
#define FXHCI_REG_OP_USBCMD_CSS (1 << 8) /* Controller Save State (CSS) - RW */
|
||
#define FXHCI_REG_OP_USBCMD_CRS (1 << 9) /* Controller Restore State (CRS) - RW */
|
||
#define FXHCI_REG_OP_USBCMD_EWE (1 << 10) /* Enable Wrap Event (EWE) - RW */
|
||
#define FXHCI_REG_OP_USBCMD_EU3S (1 << 11) /* Enable U3 MFINDEX Stop (EU3S) - RW */
|
||
|
||
/** @name FXHCI_REG_OP_USBSTS Register
|
||
*/
|
||
#define FXHCI_REG_OP_USBSTS_HCH (1 << 0) /* 1: Stopped executing */
|
||
#define FXHCI_REG_OP_USBSTS_HSE (1 << 2) /* 1: Serious error detected */
|
||
#define FXHCI_REG_OP_USBSTS_EINT (1 << 3) /* 1: Interrupt Pending (IP) */
|
||
#define FXHCI_REG_OP_USBSTS_PCD (1 << 4) /* 1: Port Change Detect */
|
||
#define FXHCI_REG_OP_USBSTS_SSS (1 << 8) /* remain 1 while the xHC saves its internal state */
|
||
#define FXHCI_REG_OP_USBSTS_RSS (1 << 9) /* remain 1 while the xHC restores its internal state */
|
||
#define FXHCI_REG_OP_USBSTS_SRE (1 << 10) /* if error occurs during a Save or Restore operation this bit shall be set to ‘1’. */
|
||
#define FXHCI_REG_OP_USBSTS_CNR (1 << 11) /* 1: Controller Not Ready */
|
||
#define FXHCI_REG_OP_USBSTS_HCE (1 << 12) /* 1: Internal xHC error condition */
|
||
#define FXHCI_REG_OP_USBSTS_PRSRV_MASK ((1 << 1) | 0xffffe000) /* Rsvd bits */
|
||
|
||
/** @name FXHCI_REG_OP_PAGESIZE Register
|
||
*/
|
||
/* This xHC supports a page size of 2^(n+12) if bit n is Set */
|
||
#define FXHCI_REG_OP_PAGESIZE_4K (1 << 0) /* if bit 0 is Set, the xHC supports 4k byte page sizes */
|
||
|
||
/** @name FXHCI_REG_OP_CRCR Register
|
||
*/
|
||
#define FXHCI_REG_OP_CRCR_RCS (1 << 0) /* Ring Cycle State, value of the xHC Consumer Cycle State (CCS) flag */
|
||
#define FXHCI_REG_OP_CRCR_CS (1 << 1) /* Command Stop, 1 */
|
||
#define FXHCI_REG_OP_CRCR_CA (1 << 2) /* Command Abort, 1 */
|
||
#define FXHCI_REG_OP_CRCR_CRR (1 << 3) /* Command Ring Running */
|
||
#define FXHCI_REG_OP_CRCR_CR_PTR_MASK GENMASK_ULL(63, 6) /* Command Ring Pointer, Dequeue Ptr of Command Ring */
|
||
|
||
/** @name FXHCI_REG_OP_DCBAAP Register
|
||
*/
|
||
#define FXHCI_REG_OP_DCBAAP_MASK GENMASK_ULL(63, 6) /* bit[31:6] Ptr of DCBAA */
|
||
|
||
/** @name FXHCI_REG_OP_CONFIG Register
|
||
*/
|
||
#define FXHCI_REG_OP_CONFIG_MAX_SLOTS_EN_MASK GENMASK(7, 0) /* Max Device Slots Enabled (MaxSlotsEn) – RW */
|
||
#define FXHCI_REG_OP_CONFIG_MAX_SLOTS_EN_SET(x) FUSB_REG32_SET_BITS(x, 7, 0) /* bit[7:0] Max Device Slots Enabled */
|
||
#define FXHCI_REG_OP_CONFIG_MAX_SLOTS_EN_GET(x) FUSB_REG32_GET_BITS(x, 7, 0)
|
||
|
||
/** @name FXHCI_REG_OP_PORTS_PORTSC Register
|
||
*/
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_CCS (1 << 0) /* Current Connect Status (CCS) – ROS */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PED (1 << 1) /* Port Enabled/Disabled (PED) – RW1CS */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_OCA (1 << 3) /* Over-current Active (OCA) – RO */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PR (1 << 4) /* Port Reset (PR) – RW1S */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLS_GET(x) FUSB_REG32_GET_BITS(x, 8, 5) /* Port Link State (PLS) – RWS */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) FUSB_REG32_SET_BITS(x, 8, 5)
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLS_MASK GENMASK(8, 5)
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLS(x) (x << 5)
|
||
/* Read value of Port Link State (PLS) */
|
||
/* refer to FXHCI doc page-408 for details (Port Link State) */
|
||
enum
|
||
{
|
||
FXHCI_LINK_STATE_U0 = 0, /* U0 State */
|
||
FXHCI_LINK_STATE_U1 = 1, /* U1 State */
|
||
FXHCI_LINK_STATE_U2 = 2, /* U2 State */
|
||
FXHCI_LINK_STATE_U3 = 3, /* U3 State (Device Suspended) */
|
||
FXHCI_LINK_STATE_DISABLED = 4, /* Disabled State */
|
||
FXHCI_LINK_STATE_RX_DETECT = 5, /* RxDetect State (Disconnected) */
|
||
FXHCI_LINK_STATE_INACTIVE = 6, /* Inactive State */
|
||
FXHCI_LINK_STATE_POLLING = 7, /* Polling State */
|
||
FXHCI_LINK_STATE_RECOVERY = 8, /* Recovery State */
|
||
FXHCI_LINK_STATE_HOT_RESET = 9, /* Hot Reset State */
|
||
FXHCI_LINK_STATE_COMPLIANCE_MODE = 10, /* Compliance Mode State */
|
||
FXHCI_LINK_STATE_TEST_MODE = 11, /* Test Mode State */
|
||
FXHCI_LINK_STATE_RESUME = 15, /* Resume State */
|
||
|
||
FXHCI_LINK_STATE_MAX
|
||
};
|
||
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLS_SET(x) FUSB_REG32_SET_BITS(x, 8, 5)
|
||
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PP (1 << 9) /* Port Power (PP) – RWS */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PORT_SPEED_GET(x) FUSB_REG32_GET_BITS(x, 13, 10) /* Port Speed (Port Speed) – ROS */
|
||
/* Protocol Speed ID (PSI) 1~15 */
|
||
enum
|
||
{
|
||
FXHCI_PORT_SPEED_UNDEFINED = 0,
|
||
FXHCI_PORT_SPEED_1 = 1,
|
||
FXHCI_PORT_SPEED_15 = 15,
|
||
};
|
||
|
||
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PIC_SET(x) FUSB_REG32_SET_BITS(x, 15, 14)
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PIC_MASK GENMASK(15, 14)
|
||
enum
|
||
{
|
||
FXHCI_PORT_INDICATOR_OFF = 0,
|
||
FXHCI_PORT_INDICATOR_AMBER = 1,
|
||
FXHCI_PORT_INDICATOR_GREEN = 2,
|
||
FXHCI_PORT_INDICATOR_UNDEFINED = 3
|
||
};
|
||
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_LWS (1 << 16) /* Port Link State Write Strobe (LWS) */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_CSC (1 << 17) /* Connect Status Change (CSC) */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PEC (1 << 18) /* Port Enabled/Disabled Change (PEC) 1: clear PED */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_WRC (1 << 19) /* Warm Port Reset Change 1: Warm Reset complete */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_OCC (1 << 20) /* Over-current Change 1: Over-current Active */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PRC (1 << 21) /* Port Reset Change 1: Transition of Port Reset */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_PLC (1 << 22) /* Port Link State Change 1: PLS transition */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_CEC (1 << 23) /* Port Config Error Change 1: Port Config Error detected */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_CAS (1 << 24) /* Cold Attach Status 1: Far-end Receiver Terminations were detected */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_WCE (1 << 25) /* Wake on Connect Enable 1: enable port to be sensitive to device connects */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_WDE (1 << 26) /* Wake on Disconnect Enable 1: enable port to be sensitive to device disconnects */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_WOE (1 << 27) /* Wake on Over-current Enable 1: enable port to be sensitive to over-current conditions */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_DR (1 << 30) /* Device Removable, 0: Device is removable. 1: Device is non-removable */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_WPR (1 << 31) /* Warm Port Reset 1: follow Warm Reset sequence */
|
||
#define FXHCI_REG_OP_PORTS_PORTSC_RW_MASK (FXHCI_REG_OP_PORTS_PORTSC_PR | FXHCI_REG_OP_PORTS_PORTSC_PLS_MASK | FXHCI_REG_OP_PORTS_PORTSC_PP \
|
||
| FXHCI_REG_OP_PORTS_PORTSC_PIC_MASK | FXHCI_REG_OP_PORTS_PORTSC_LWS | FXHCI_REG_OP_PORTS_PORTSC_WCE \
|
||
| FXHCI_REG_OP_PORTS_PORTSC_WDE | FXHCI_REG_OP_PORTS_PORTSC_WOE)
|
||
|
||
/***************** Host Controller Runtime Registers ***********************/
|
||
|
||
/** @name FXHCI_REG_RT_IR_IMAN Register
|
||
*/
|
||
#define FXHCI_REG_RT_IR_IMAN_IP (1 << 0) /* Interrupt Pending, 1: an interrupt is pending for this Interrupter */
|
||
#define FXHCI_REG_RT_IR_IMAN_IE (1 << 1) /* Interrupt Enable, 1: capable of generating an interrupt. */
|
||
|
||
/** @name FXHCI_REG_RT_IR_IMOD Register
|
||
*/
|
||
#define FXHCI_REG_RT_IR_IMOD_IMODI_MASK GENMASK(15, 0) /* bit[15:0] Interrupt Moderation Interval default 4000 ==> 1ms */
|
||
#define FXHCI_REG_RT_IR_IMOD_IMODC_MASK GENMASK(31, 16) /* bit[31:16] Interrupt Moderation Counter(Down counter) */
|
||
|
||
/** @name FXHCI_REG_RT_IR_ERSTSZ Register
|
||
*/
|
||
#define FXHCI_REG_RT_IR_ERSTSZ_MASK GENMASK(15, 0) /* bit[15:0] the number of valid Event Ring Segment Table entries */
|
||
|
||
/** @name FXHCI_REG_RT_IR_ERSTBA Register
|
||
*/
|
||
#define FXHCI_REG_RT_IR_ERSTBA_MASK GENMASK_ULL(63, 6) /* Event Ring Segment Table Base Address */
|
||
|
||
/** @name FXHCI_REG_RT_IR_ERDP Register
|
||
*/
|
||
#define FXHCI_REG_RT_IR_ERDP_DESI_MASK GENMASK_ULL(2, 0) /* bit[2:0] Dequeue ERST Segment Index */
|
||
#define FXHCI_REG_RT_IR_ERDP_EHB (1 << 3) /* Event Handler Busy */
|
||
#define FXHCI_REG_RT_IR_ERDP_MASK GENMASK_ULL(63, 4) /* Event Ring Dequeue Pointer */
|
||
|
||
/***************** Doorbell Register ***********************/
|
||
#define FXHCI_REG_DB_TARGET_HC_COMMAND 0 /* Host Controller Doorbell (0) Command Doorbell */
|
||
#define FXHCI_REG_DB_TARGET_EP0 1 /* Device Context Doorbells Control EP 0 Enqueue Pointer Update */
|
||
#define FXHCI_REG_DB_TARGET_EP1_OUT 2 /* EP 1 OUT Enqueue Pointer Update */
|
||
#define FXHCI_REG_DB_TARGET_EP1_IN 3 /* EP 1 IN Enqueue Pointer Update */
|
||
#define FXHCI_REG_DB_TARGET_EP15_OUT 30 /* EP 15 OUT Enqueue Pointer Update */
|
||
#define FXHCI_REG_DB_TARGET_EP15_IN 31 /* EP 15 IN Enqueue Pointer Update */
|
||
|
||
/***************** xHCI Extended Capabilities Registers ***********************/
|
||
#define FXHCI_REG_EXT_CAP_CAP_ID_GET(x) FUSB_REG32_GET_BITS(x, 7, 0)
|
||
/* refer to 'Table 138: xHCI Extended Capability Codes' for more details */
|
||
enum
|
||
{
|
||
FXHCI_EXT_CAP_ID_USB_LEGACY_SUPPORT = 1,
|
||
FXHCI_EXT_CAP_ID_SUPPORT_PROTOCOL = 2,
|
||
FXHCI_EXT_CAP_ID_EXTEND_POWER_MANAGEMENT = 3,
|
||
FXHCI_EXT_CAP_ID_IO_VIRTUALIZATION = 4,
|
||
FXHCI_EXT_CAP_ID_MESSAGE_INTERRUPT = 5,
|
||
FXHCI_EXT_CAP_ID_LOCAL_MEMORY = 6,
|
||
FXHCI_EXT_CAP_ID_USB_DEBUG_CAPABILITY = 10,
|
||
FXHCI_EXT_CAP_ID_EXT_MESSAGE_INTERRUPT = 17,
|
||
|
||
FXHCI_EXT_CAP_ID_VENDOR_DEFINED_MIN = 192,
|
||
FXHCI_EXT_CAP_ID_VENDOR_DEFINED_MAX = 255
|
||
};
|
||
|
||
#define FXHCI_REG_EXT_CAP_NEXT_CAP_PTR_GET(x) FUSB_REG32_GET_BITS(x, 15, 8)
|
||
#define FXHCI_REG_EXT_CAP_CAP_SPEC_GET(x) FUSB_REG32_GET_BITS(x, 31, 16)
|
||
/* Ext capabilities specific definitions */
|
||
/* USB Legacy Support Capability */
|
||
#define FXHCI_REG_EXT_CAP_USBLEGSUP_OFFSET 0x0 /* used by pre-OS software (BIOS) and the operating system to coordinate ownership of the xHC. */
|
||
#define FXHCI_USBLEGSUP_BIOS_OWNED_SEMAPHORE (1 << 16) /* RW, The BIOS sets this bit to establish ownership of the xHC */
|
||
#define FXHCI_USBLEGSUP_OS_OWNED_SEMAPHORE (1 << 24) /* RW, System software sets this bit to request ownership of the xHC */
|
||
|
||
#define FXHCI_REG_EXT_CAP_USBLEGCTLSTS_OFFSET 0x4 /* uses this register to enable System Management Interrupts (SMIs) for every xHCI/USB event it needs to track */
|
||
#define FXHCI_USBLEGCTLSTS_USB_SMI_EN (1 << 0) /* RW, enable interrupts to trach event */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_HC_ERR_EN (1 << 4) /* RW */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_OS_OWE_EN (1 << 13) /* RW */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_PCI_CMD_EN (1 << 14) /* RW */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_BAR_EN (1 << 15) /* RW */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_EVT_INTERRUPT (1 << 16) /* RO */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_HC_SYS_ERR (1 << 20) /* RO */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_OS_OWN_CHG (1 << 29) /* RW1C */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_PCI_CMD (1 << 30) /* RW1C */
|
||
#define FXHCI_USBLEGCTLSTS_SMI_BAR (1 << 31) /* RW1C */
|
||
|
||
/* xHCI Supported Protocol Capability */
|
||
#define FXHCI_REG_EXT_CAP_USBSPCF_OFFSET 0x0
|
||
#define FXHCI_USBSPCF_MINOR_REVERSION_GET(x) FUSB_REG32_GET_BITS(x, 23, 16)
|
||
#define FXHCI_USBSPCF_MAJOR_REVERSION_GET(x) FUSB_REG32_GET_BITS(x, 31, 24)
|
||
enum
|
||
{
|
||
FXHCI_MAJOR_REVERSION_USB2 = 2,
|
||
FXHCI_MAJOR_REVERSION_USB3 = 3
|
||
};
|
||
|
||
#define FXHCI_REG_EXT_CAP_USBSPCFDEF_OFFSET 0x4
|
||
#define FXHCI_USBSPCFDEF_NAME_STRING_GET(x) FUSB_REG32_GET_BITS(x, 31, 0) /* four ASCII characters may be defined */
|
||
#define FXHCI_USBSPCFDEF_NAME_STRING_USB 0x20425355 /* ASCII = "USB" */
|
||
|
||
#define FXHCI_REG_EXT_CAP_USBSPCFDEF2_OFFSET 0x8
|
||
#define FXHCI_USBSPCFDEF2_COMPATIBLE_PORT_OFF_GET(x) FUSB_REG32_GET_BITS(x, 7, 0)
|
||
#define FXHCI_USBSPCFDEF2_COMPATIBLE_PORT_CNT_GET(x) FUSB_REG32_GET_BITS(x, 15, 8)
|
||
#define FXHCI_USBSPCFDEF2_PROTOCOL_DEFINED_GET(x) FUSB_REG32_GET_BITS(x, 27, 16)
|
||
/* USB3 - No Protocol Defined fields */
|
||
/* USB2 */
|
||
#define FXHCI_USBSPCFDEF2_USB2_HIGH_SPEED_ONLY (1 << 17) /* High-speed Only (HSO) - RO */
|
||
#define FXHCI_USBSPCFDEF2_USB2_INTERGRATED_HUB (1 << 18) /* Integrated Hub Implemented (IHI) - RO */
|
||
#define FXHCI_USBSPCFDEF2_USB2_HW_LMP_CAP (1 << 19) /* Hardware LMP Capability (HLC) - RO */
|
||
|
||
#define FXHCI_USBSPCFDEF2_PROTOCOL_SPEED_ID_CNT_GET(x) FUSB_REG32_GET_BITS(x, 31, 28)
|
||
|
||
/* Protocol Speed ID (PSI) */
|
||
#define FXHCI_REG_PROTOCOL_SPEED_ID_OFFSET(psic) (0xc + ((psic) * sizeof(u32)))
|
||
#define FXHCI_PROTOCOL_SPEED_ID_VALUE_GET(x) FUSB_REG32_GET_BITS(x, 3, 0) /* Protocol Speed ID Value (PSIV) */
|
||
#define FXHCI_PROTOCOL_SPEED_ID_EXPONENT_GET(x) FUSB_REG32_GET_BITS(x, 5, 4) /* Protocol Speed ID Exponent (PSIE) */
|
||
#define FXHCI_PROTOCOL_SPEED_ID_PSI_TYPE_GET(x) FUSB_REG32_GET_BITS(x, 7, 6) /* PSI Type (PLT) */
|
||
enum
|
||
{
|
||
FXHCI_PROTOCOL_SPEED_ID_PSI_SYMMETRIC = 0,
|
||
FXHCI_PROTOCOL_SPEED_ID_PSI_ASYMMETRIC_RX = 2,
|
||
FXHCI_PROTOCOL_SPEED_ID_PSI_ASYMMETRIC_TX = 3
|
||
};
|
||
#define FXHCI_PROTOCOL_SPEED_ID_PSI_FULL_DUPLEX (1 << 8)
|
||
#define FXHCI_PROTOCOL_SPEED_ID_MANTISSA_GET(x) FUSB_REG32_GET_BITS(x, 31, 16) /* Protocol Speed ID Mantissa (PSIM) */
|
||
|
||
/**************************** Type Definitions *******************************/
|
||
|
||
/* Device Context Base Address Array */
|
||
#define FXHCI_SCRATCHPAD_BUF_ARRAY_BASE_ADDR_MASK GENMASK_ULL(63, 6) /* Array Element 0 Field Bit */
|
||
#define FXHCI_DEVICE_CONTEXT_BASE_ADDR_MASK GENMASK_ULL(63, 6) /* Array Element 1-n Field Bit */
|
||
|
||
/* Slot index */
|
||
#define FXHCI_REG_DB_HOST_CONTROLLER 0
|
||
#define FXHCI_REG_DB_DEVICE_CONTEXT1 1
|
||
#define FXHCI_REG_DB_DEVICE_CONTEXT255 255
|
||
|
||
typedef struct
|
||
{
|
||
u8 port_beg;
|
||
u8 port_end;
|
||
} FXhciPortRange;
|
||
|
||
typedef enum
|
||
{
|
||
FXHCI_USB2_COMPATIBLE_PORT,
|
||
FXHCI_USB3_COMPATIBLE_PORT,
|
||
|
||
FXHCI_NONE_COMPATIBLE_PORT
|
||
} FXhciPortCompatible;
|
||
|
||
typedef struct
|
||
{
|
||
uintptr base; /* Capability registers offset */
|
||
uintptr oper_base; /* Operational registers offset */
|
||
uintptr doorbell_base; /* Doorbell registers offset */
|
||
uintptr runtime_base; /* Runtime registers offset */
|
||
uintptr port_base; /* Port register set offset */
|
||
uintptr xecp_base; /* xHCI Extended Capabilities register offset */
|
||
u32 hcx_params[4]; /* Capability cache */
|
||
FXhciPortRange usb2_ports;
|
||
FXhciPortRange usb3_ports;
|
||
} FXhciMMIO;
|
||
|
||
|
||
/************************** Variable Definitions *****************************/
|
||
|
||
/***************** Macros (Inline Functions) Definitions *********************/
|
||
static inline FXhciPortCompatible FUsb3CheckPortCompatible(FXhciMMIO *mmio, u8 port_id)
|
||
{
|
||
FASSERT(mmio);
|
||
if ((port_id >= mmio->usb3_ports.port_beg) && (port_id <= mmio->usb3_ports.port_end))
|
||
{
|
||
return FXHCI_USB3_COMPATIBLE_PORT;
|
||
}
|
||
else if ((port_id >= mmio->usb2_ports.port_beg) && (port_id <= mmio->usb2_ports.port_end))
|
||
{
|
||
return FXHCI_USB2_COMPATIBLE_PORT;
|
||
}
|
||
|
||
FASSERT(0); /* must not reach there */
|
||
return FXHCI_NONE_COMPATIBLE_PORT;
|
||
}
|
||
|
||
static inline u32 FXhciReadCap(const FXhciMMIO *mmio)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
return FtIn32(mmio->base + FXHCI_REG_CAP_CAPLENGTH);
|
||
}
|
||
|
||
static inline u8 FXhciReadCaplen(const FXhciMMIO *mmio)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
u32 reg_val = FXhciReadCap(mmio);
|
||
|
||
/* get lower 8-bits */
|
||
return (u8)(reg_val & 0xff);
|
||
}
|
||
|
||
static inline u16 FXhciReadHcVersion(const FXhciMMIO *mmio)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
u32 reg_val = FXhciReadCap(mmio);
|
||
|
||
/* get upper 16 bits */
|
||
return (u16)((reg_val >> 16) & 0xffff);
|
||
}
|
||
|
||
static inline u32 FXhciReadCap32(const FXhciMMIO *mmio, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
offset -= FXHCI_REG_CAP_HCSPARAMS1;
|
||
offset /= 4;
|
||
|
||
FASSERT(offset < 4);
|
||
return mmio->hcx_params[offset]; /* read caps from cache */
|
||
}
|
||
|
||
static inline u32 FXhciReadOper32(const FXhciMMIO *mmio, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
return FtIn32(mmio->oper_base + offset);
|
||
}
|
||
|
||
static inline u64 FXhciReadOper64(const FXhciMMIO *mmio, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
uintptr addr = mmio->oper_base + offset;
|
||
|
||
u64 val = FtIn32(addr);
|
||
val |= ((u64)FtIn32(addr + 4)) << 32;
|
||
|
||
return val;
|
||
}
|
||
|
||
static inline void FXhciWriteOper32(const FXhciMMIO *mmio, u32 offset, u32 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FtOut32(mmio->oper_base + offset, val);
|
||
}
|
||
|
||
static inline void FXhciWriteOper64(const FXhciMMIO *mmio, u32 offset, u64 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FXhciWriteOper32(mmio, offset, LOWER_32_BITS(val));
|
||
FXhciWriteOper32(mmio, offset + 4, UPPER_32_BITS(val));
|
||
}
|
||
|
||
static inline u32 FXhciReadPort32(const FXhciMMIO *mmio, u32 port, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
/* Operational Base + (400h + (10h * (n–1))) */
|
||
return FtIn32(mmio->port_base + port * FXHCI_REG_OP_PORTS_SIZE + offset);
|
||
}
|
||
|
||
static inline void FXhciWritePort32(const FXhciMMIO *mmio, u32 port, u32 offset, u32 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FtOut32(mmio->port_base + port * FXHCI_REG_OP_PORTS_SIZE + offset, val);
|
||
}
|
||
|
||
static inline u32 FXhciReadRt32(const FXhciMMIO *mmio, u32 interrupt, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
/* Runtime Base + 020h + (32 * Interrupter) */
|
||
return FtIn32(mmio->runtime_base + FXHCI_REG_RT_IR0 + interrupt * FXHCI_REG_RT_IR_SIZE + offset);
|
||
}
|
||
|
||
static inline u64 FXhciReadRt64(const FXhciMMIO *mmio, u32 interrupt, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
uintptr addr = mmio->runtime_base + FXHCI_REG_RT_IR0 + interrupt * FXHCI_REG_RT_IR_SIZE + offset;
|
||
u64 reg_val = FtIn32(addr);
|
||
reg_val |= (u64)FtIn32(addr + 4) << 32;
|
||
|
||
return reg_val;
|
||
}
|
||
|
||
static inline void FXhciWriteRt32(const FXhciMMIO *mmio, u32 interrupt, u32 offset, u32 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FtOut32(mmio->runtime_base + FXHCI_REG_RT_IR0 + interrupt * FXHCI_REG_RT_IR_SIZE + offset, val);
|
||
}
|
||
|
||
static inline void FXhciWriteRt64(const FXhciMMIO *mmio, u32 interrupt, u32 offset, u64 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FXhciWriteRt32(mmio, interrupt, offset, (u32)val);
|
||
FXhciWriteRt32(mmio, interrupt, offset + 4, (u32)(val >> 32));
|
||
}
|
||
|
||
static inline u32 FXhciReadExtCap32(const FXhciMMIO *mmio, u32 offset)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
FASSERT(mmio->xecp_base != 0);
|
||
|
||
return FtIn32(mmio->xecp_base + offset);
|
||
}
|
||
|
||
static inline void FXhciWriteDb32(const FXhciMMIO *mmio, u32 slot, u32 val)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
FtOut32(mmio->doorbell_base + slot * FXHCI_REG_DB_SIZE, val);
|
||
}
|
||
|
||
static inline int FXhciGetCtxSize(const FXhciMMIO *mmio)
|
||
{
|
||
FASSERT(mmio);
|
||
FASSERT(mmio->base != 0);
|
||
|
||
u32 reg_val = FXhciReadCap32(mmio, FXHCI_REG_CAP_HCCPARAMS);
|
||
return ((reg_val & FXHCI_REG_CAP_HCCPARAMS_CSZ) == FXHCI_REG_CAP_HCCPARAMS_CSZ) ? 64 : 32;
|
||
}
|
||
|
||
/************************** Function Prototypes ******************************/
|
||
FError FXhciSetupMMIO(FXhciMMIO *mmio, uintptr base_addr);
|
||
void FXhciListExtCap(FXhciMMIO *mmio);
|
||
FError FXhciWaitOper32(FXhciMMIO *mmio, u32 offset, u32 mask, u32 exp_val, u32 timeout_tick);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
|
||
#endif |