/** @file

  This file contains the register definition of XHCI host controller.

Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent

**/

#ifndef _EFI_XHCI_REG_H_
#define _EFI_XHCI_REG_H_

#define PCI_IF_XHCI                 0x30

//
// PCI Configuration Registers
//
#define XHC_BAR_INDEX               0x00

#define XHC_PCI_BAR_OFFSET          0x10       // Memory Bar Register Offset
#define XHC_PCI_BAR_MASK            0xFFFF     // Memory Base Address Mask

#define XHC_PCI_SBRN_OFFSET         0x60       // Serial Bus Release Number Register Offset

#define USB_HUB_CLASS_CODE          0x09
#define USB_HUB_SUBCLASS_CODE       0x00

#define XHC_CAP_USB_LEGACY          0x01
#define XHC_CAP_USB_DEBUG           0x0A

//============================================//
//           XHCI register offset             //
//============================================//

//
// Capability registers offset
//
#define XHC_CAPLENGTH_OFFSET               0x00 // Capability register length offset
#define XHC_HCIVERSION_OFFSET              0x02 // Interface Version Number 02-03h
#define XHC_HCSPARAMS1_OFFSET              0x04 // Structural Parameters 1
#define XHC_HCSPARAMS2_OFFSET              0x08 // Structural Parameters 2
#define XHC_HCSPARAMS3_OFFSET              0x0c // Structural Parameters 3
#define XHC_HCCPARAMS_OFFSET               0x10 // Capability Parameters
#define XHC_DBOFF_OFFSET                   0x14 // Doorbell Offset
#define XHC_RTSOFF_OFFSET                  0x18 // Runtime Register Space Offset

//
// Operational registers offset
//
#define XHC_USBCMD_OFFSET                  0x0000 // USB Command Register Offset
#define XHC_USBSTS_OFFSET                  0x0004 // USB Status Register Offset
#define XHC_PAGESIZE_OFFSET                0x0008 // USB Page Size Register Offset
#define XHC_DNCTRL_OFFSET                  0x0014 // Device Notification Control Register Offset
#define XHC_CRCR_OFFSET                    0x0018 // Command Ring Control Register Offset
#define XHC_DCBAAP_OFFSET                  0x0030 // Device Context Base Address Array Pointer Register Offset
#define XHC_CONFIG_OFFSET                  0x0038 // Configure Register Offset
#define XHC_PORTSC_OFFSET                  0x0400 // Port Status and Control Register Offset

//
// Runtime registers offset
//
#define XHC_MFINDEX_OFFSET                 0x00 // Microframe Index Register Offset
#define XHC_IMAN_OFFSET                    0x20 // Interrupter X Management Register Offset
#define XHC_IMOD_OFFSET                    0x24 // Interrupter X Moderation Register Offset
#define XHC_ERSTSZ_OFFSET                  0x28 // Event Ring Segment Table Size Register Offset
#define XHC_ERSTBA_OFFSET                  0x30 // Event Ring Segment Table Base Address Register Offset
#define XHC_ERDP_OFFSET                    0x38 // Event Ring Dequeue Pointer Register Offset

//
// Debug registers offset
//
#define XHC_DC_DCCTRL                      0x20

#define USBLEGSP_BIOS_SEMAPHORE            BIT16 // HC BIOS Owned Semaphore
#define USBLEGSP_OS_SEMAPHORE              BIT24 // HC OS Owned Semaphore

#pragma pack (1)
typedef struct {
  UINT8                   MaxSlots;       // Number of Device Slots
  UINT16                  MaxIntrs:11;    // Number of Interrupters
  UINT16                  Rsvd:5;
  UINT8                   MaxPorts;       // Number of Ports
} HCSPARAMS1;

//
// Structural Parameters 1 Register Bitmap Definition
//
typedef union {
  UINT32                  Dword;
  HCSPARAMS1              Data;
} XHC_HCSPARAMS1;

typedef struct {
  UINT32                  Ist:4;          // Isochronous Scheduling Threshold
  UINT32                  Erst:4;         // Event Ring Segment Table Max
  UINT32                  Rsvd:13;
  UINT32                  ScratchBufHi:5; // Max Scratchpad Buffers Hi
  UINT32                  Spr:1;          // Scratchpad Restore
  UINT32                  ScratchBufLo:5; // Max Scratchpad Buffers Lo
} HCSPARAMS2;

//
// Structural Parameters 2 Register Bitmap Definition
//
typedef union {
  UINT32                  Dword;
  HCSPARAMS2              Data;
} XHC_HCSPARAMS2;

typedef struct {
  UINT16                  Ac64:1;        // 64-bit Addressing Capability
  UINT16                  Bnc:1;         // BW Negotiation Capability
  UINT16                  Csz:1;         // Context Size
  UINT16                  Ppc:1;         // Port Power Control
  UINT16                  Pind:1;        // Port Indicators
  UINT16                  Lhrc:1;        // Light HC Reset Capability
  UINT16                  Ltc:1;         // Latency Tolerance Messaging Capability
  UINT16                  Nss:1;         // No Secondary SID Support
  UINT16                  Pae:1;         // Parse All Event Data
  UINT16                  Rsvd:3;
  UINT16                  MaxPsaSize:4;  // Maximum Primary Stream Array Size
  UINT16                  ExtCapReg;     // xHCI Extended Capabilities Pointer
} HCCPARAMS;

//
// Capability Parameters Register Bitmap Definition
//
typedef union {
  UINT32                  Dword;
  HCCPARAMS               Data;
} XHC_HCCPARAMS;

#pragma pack ()

//
// Register Bit Definition
//
#define XHC_USBCMD_RUN                     BIT0  // Run/Stop
#define XHC_USBCMD_RESET                   BIT1  // Host Controller Reset
#define XHC_USBCMD_INTE                    BIT2  // Interrupter Enable
#define XHC_USBCMD_HSEE                    BIT3  // Host System Error Enable

#define XHC_USBSTS_HALT                    BIT0  // Host Controller Halted
#define XHC_USBSTS_HSE                     BIT2  // Host System Error
#define XHC_USBSTS_EINT                    BIT3  // Event Interrupt
#define XHC_USBSTS_PCD                     BIT4  // Port Change Detect
#define XHC_USBSTS_SSS                     BIT8  // Save State Status
#define XHC_USBSTS_RSS                     BIT9  // Restore State Status
#define XHC_USBSTS_SRE                     BIT10 // Save/Restore Error
#define XHC_USBSTS_CNR                     BIT11 // Host Controller Not Ready
#define XHC_USBSTS_HCE                     BIT12 // Host Controller Error

#define XHC_PAGESIZE_MASK                  0xFFFF // Page Size

#define XHC_CRCR_RCS                       BIT0  // Ring Cycle State
#define XHC_CRCR_CS                        BIT1  // Command Stop
#define XHC_CRCR_CA                        BIT2  // Command Abort
#define XHC_CRCR_CRR                       BIT3  // Command Ring Running

#define XHC_CONFIG_MASK                    0xFF  // Command Ring Running

#define XHC_PORTSC_CCS                     BIT0  // Current Connect Status
#define XHC_PORTSC_PED                     BIT1  // Port Enabled/Disabled
#define XHC_PORTSC_OCA                     BIT3  // Over-current Active
#define XHC_PORTSC_RESET                   BIT4  // Port Reset
#define XHC_PORTSC_PLS                     (BIT5|BIT6|BIT7|BIT8)     // Port Link State
#define XHC_PORTSC_PP                      BIT9  // Port Power
#define XHC_PORTSC_PS                      (BIT10|BIT11|BIT12|BIT13) // Port Speed
#define XHC_PORTSC_LWS                     BIT16 // Port Link State Write Strobe
#define XHC_PORTSC_CSC                     BIT17 // Connect Status Change
#define XHC_PORTSC_PEC                     BIT18 // Port Enabled/Disabled Change
#define XHC_PORTSC_WRC                     BIT19 // Warm Port Reset Change
#define XHC_PORTSC_OCC                     BIT20 // Over-Current Change
#define XHC_PORTSC_PRC                     BIT21 // Port Reset Change
#define XHC_PORTSC_PLC                     BIT22 // Port Link State Change
#define XHC_PORTSC_CEC                     BIT23 // Port Config Error Change
#define XHC_PORTSC_CAS                     BIT24 // Cold Attach Status

#define XHC_HUB_PORTSC_CCS                 BIT0  // Hub's Current Connect Status
#define XHC_HUB_PORTSC_PED                 BIT1  // Hub's Port Enabled/Disabled
#define XHC_HUB_PORTSC_OCA                 BIT3  // Hub's Over-current Active
#define XHC_HUB_PORTSC_RESET               BIT4  // Hub's Port Reset
#define XHC_HUB_PORTSC_PP                  BIT9  // Hub's Port Power
#define XHC_HUB_PORTSC_CSC                 BIT16 // Hub's Connect Status Change
#define XHC_HUB_PORTSC_PEC                 BIT17 // Hub's Port Enabled/Disabled Change
#define XHC_HUB_PORTSC_OCC                 BIT19 // Hub's Over-Current Change
#define XHC_HUB_PORTSC_PRC                 BIT20 // Hub's Port Reset Change
#define XHC_HUB_PORTSC_BHRC                BIT21 // Hub's Port Warm Reset Change
#define XHC_IMAN_IP                        BIT0  // Interrupt Pending
#define XHC_IMAN_IE                        BIT1  // Interrupt Enable

#define XHC_IMODI_MASK                     0x0000FFFF  // Interrupt Moderation Interval
#define XHC_IMODC_MASK                     0xFFFF0000  // Interrupt Moderation Counter

//
//  Hub Class Feature Selector for Clear Port Feature Request
//  It's the extension of hub class feature selector of USB 2.0 in USB 3.0 Spec.
//  For more details, Please refer to USB 3.0 Spec Table 10-7.
//
typedef enum {
  Usb3PortBHPortReset          = 28,
  Usb3PortBHPortResetChange    = 29
} XHC_PORT_FEATURE;

//
// Structure to map the hardware port states to the
// UEFI's port states.
//
typedef struct {
  UINT32                  HwState;
  UINT16                  UefiState;
} USB_PORT_STATE_MAP;

//
// Structure to map the hardware port states to feature selector for clear port feature request.
//
typedef struct {
  UINT32                  HwState;
  UINT16                  Selector;
} USB_CLEAR_PORT_MAP;

/**
  Read 1-byte width XHCI capability register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the 1-byte width capability register.

  @return The register content read.
  @retval If err, return 0xFFFF.

**/
UINT8
XhcReadCapReg8 (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Read 4-bytes width XHCI capability register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the 4-bytes width capability register.

  @return The register content read.
  @retval If err, return 0xFFFFFFFF.

**/
UINT32
XhcReadCapReg (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Read 4-bytes width XHCI Operational register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the 4-bytes width operational register.

  @return The register content read.
  @retval If err, return 0xFFFFFFFF.

**/
UINT32
XhcReadOpReg (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Write the data to the 4-bytes width XHCI operational register.

  @param  Xhc      The XHCI Instance.
  @param  Offset   The offset of the 4-bytes width operational register.
  @param  Data     The data to write.

**/
VOID
XhcWriteOpReg (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Data
  );


/**
  Read XHCI runtime register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.

  @return The register content read

**/
UINT32
XhcReadRuntimeReg (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Write the data to the XHCI runtime register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.
  @param  Data         The data to write.

**/
VOID
XhcWriteRuntimeReg (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Data
  );


/**
  Write the data to the XHCI door bell register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the door bell register.
  @param  Data         The data to write.

**/
VOID
XhcWriteDoorBellReg (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Data
  );

/**
  Set one bit of the operational register while keeping other bits.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the operational register.
  @param  Bit          The bit mask of the register to set.

**/
VOID
XhcSetOpRegBit (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Bit
  );

/**
  Clear one bit of the operational register while keeping other bits.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the operational register.
  @param  Bit          The bit mask of the register to clear.

**/
VOID
XhcClearOpRegBit (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Bit
  );

/**
  Wait the operation register's bit as specified by Bit
  to be set (or clear).

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the operational register.
  @param  Bit          The bit of the register to wait for.
  @param  WaitToSet    Wait the bit to set or clear.
  @param  Timeout      The time to wait before abort (in millisecond, ms).

  @retval EFI_SUCCESS  The bit successfully changed by host controller.
  @retval EFI_TIMEOUT  The time out occurred.

**/
EFI_STATUS
XhcWaitOpRegBit (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Bit,
  IN BOOLEAN              WaitToSet,
  IN UINT32               Timeout
  );

/**
  Read XHCI runtime register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.

  @return The register content read

**/
UINT32
XhcReadRuntimeReg (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Write the data to the XHCI runtime register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.
  @param  Data         The data to write.

**/
VOID
XhcWriteRuntimeReg (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Data
  );

/**
  Set one bit of the runtime register while keeping other bits.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.
  @param  Bit          The bit mask of the register to set.

**/
VOID
XhcSetRuntimeRegBit (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Bit
  );

/**
  Clear one bit of the runtime register while keeping other bits.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the runtime register.
  @param  Bit          The bit mask of the register to set.

**/
VOID
XhcClearRuntimeRegBit (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Offset,
  IN UINT32               Bit
  );

/**
  Read XHCI extended capability register.

  @param  Xhc          The XHCI Instance.
  @param  Offset       The offset of the extended capability register.

  @return The register content read

**/
UINT32
XhcReadExtCapReg (
  IN  USB_XHCI_INSTANCE   *Xhc,
  IN  UINT32              Offset
  );

/**
  Whether the XHCI host controller is halted.

  @param  Xhc     The XHCI Instance.

  @retval TRUE    The controller is halted.
  @retval FALSE   It isn't halted.

**/
BOOLEAN
XhcIsHalt (
  IN USB_XHCI_INSTANCE    *Xhc
  );

/**
  Whether system error occurred.

  @param  Xhc      The XHCI Instance.

  @retval TRUE     System error happened.
  @retval FALSE    No system error.

**/
BOOLEAN
XhcIsSysError (
  IN USB_XHCI_INSTANCE    *Xhc
  );

/**
  Reset the XHCI host controller.

  @param  Xhc          The XHCI Instance.
  @param  Timeout      Time to wait before abort (in millisecond, ms).

  @retval EFI_SUCCESS  The XHCI host controller is reset.
  @return Others       Failed to reset the XHCI before Timeout.

**/
EFI_STATUS
XhcResetHC (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Timeout
  );

/**
  Halt the XHCI host controller.

  @param  Xhc          The XHCI Instance.
  @param  Timeout      Time to wait before abort (in millisecond, ms).

  @return EFI_SUCCESS  The XHCI host controller is halt.
  @return EFI_TIMEOUT  Failed to halt the XHCI before Timeout.

**/
EFI_STATUS
XhcHaltHC (
  IN USB_XHCI_INSTANCE   *Xhc,
  IN UINT32              Timeout
  );

/**
  Set the XHCI host controller to run.

  @param  Xhc          The XHCI Instance.
  @param  Timeout      Time to wait before abort (in millisecond, ms).

  @return EFI_SUCCESS  The XHCI host controller is running.
  @return EFI_TIMEOUT  Failed to set the XHCI to run before Timeout.

**/
EFI_STATUS
XhcRunHC (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT32               Timeout
  );

/**
  Calculate the offset of the XHCI capability.

  @param  Xhc     The XHCI Instance.
  @param  CapId   The XHCI Capability ID.

  @return The offset of XHCI legacy support capability register.

**/
UINT32
XhcGetCapabilityAddr (
  IN USB_XHCI_INSTANCE    *Xhc,
  IN UINT8                CapId
  );

#endif