162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * xHCI host controller driver 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2008 Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Author: Sarah Sharp 962306a36Sopenharmony_ci * Some code borrowed from the Linux EHCI driver. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef __LINUX_XHCI_HCD_H 1362306a36Sopenharmony_ci#define __LINUX_XHCI_HCD_H 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/usb.h> 1662306a36Sopenharmony_ci#include <linux/timer.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/usb/hcd.h> 1962306a36Sopenharmony_ci#include <linux/io-64-nonatomic-lo-hi.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Code sharing between pci-quirks and xhci hcd */ 2262306a36Sopenharmony_ci#include "xhci-ext-caps.h" 2362306a36Sopenharmony_ci#include "pci-quirks.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* max buffer size for trace and debug messages */ 2662306a36Sopenharmony_ci#define XHCI_MSG_MAX 500 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci/* xHCI PCI Configuration Registers */ 2962306a36Sopenharmony_ci#define XHCI_SBRN_OFFSET (0x60) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* Max number of USB devices for any host controller - limit in section 6.1 */ 3262306a36Sopenharmony_ci#define MAX_HC_SLOTS 256 3362306a36Sopenharmony_ci/* Section 5.3.3 - MaxPorts */ 3462306a36Sopenharmony_ci#define MAX_HC_PORTS 127 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * xHCI register interface. 3862306a36Sopenharmony_ci * This corresponds to the eXtensible Host Controller Interface (xHCI) 3962306a36Sopenharmony_ci * Revision 0.95 specification 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/** 4362306a36Sopenharmony_ci * struct xhci_cap_regs - xHCI Host Controller Capability Registers. 4462306a36Sopenharmony_ci * @hc_capbase: length of the capabilities register and HC version number 4562306a36Sopenharmony_ci * @hcs_params1: HCSPARAMS1 - Structural Parameters 1 4662306a36Sopenharmony_ci * @hcs_params2: HCSPARAMS2 - Structural Parameters 2 4762306a36Sopenharmony_ci * @hcs_params3: HCSPARAMS3 - Structural Parameters 3 4862306a36Sopenharmony_ci * @hcc_params: HCCPARAMS - Capability Parameters 4962306a36Sopenharmony_ci * @db_off: DBOFF - Doorbell array offset 5062306a36Sopenharmony_ci * @run_regs_off: RTSOFF - Runtime register space offset 5162306a36Sopenharmony_ci * @hcc_params2: HCCPARAMS2 Capability Parameters 2, xhci 1.1 only 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistruct xhci_cap_regs { 5462306a36Sopenharmony_ci __le32 hc_capbase; 5562306a36Sopenharmony_ci __le32 hcs_params1; 5662306a36Sopenharmony_ci __le32 hcs_params2; 5762306a36Sopenharmony_ci __le32 hcs_params3; 5862306a36Sopenharmony_ci __le32 hcc_params; 5962306a36Sopenharmony_ci __le32 db_off; 6062306a36Sopenharmony_ci __le32 run_regs_off; 6162306a36Sopenharmony_ci __le32 hcc_params2; /* xhci 1.1 */ 6262306a36Sopenharmony_ci /* Reserved up to (CAPLENGTH - 0x1C) */ 6362306a36Sopenharmony_ci}; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* hc_capbase bitmasks */ 6662306a36Sopenharmony_ci/* bits 7:0 - how long is the Capabilities register */ 6762306a36Sopenharmony_ci#define HC_LENGTH(p) XHCI_HC_LENGTH(p) 6862306a36Sopenharmony_ci/* bits 31:16 */ 6962306a36Sopenharmony_ci#define HC_VERSION(p) (((p) >> 16) & 0xffff) 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* HCSPARAMS1 - hcs_params1 - bitmasks */ 7262306a36Sopenharmony_ci/* bits 0:7, Max Device Slots */ 7362306a36Sopenharmony_ci#define HCS_MAX_SLOTS(p) (((p) >> 0) & 0xff) 7462306a36Sopenharmony_ci#define HCS_SLOTS_MASK 0xff 7562306a36Sopenharmony_ci/* bits 8:18, Max Interrupters */ 7662306a36Sopenharmony_ci#define HCS_MAX_INTRS(p) (((p) >> 8) & 0x7ff) 7762306a36Sopenharmony_ci/* bits 24:31, Max Ports - max value is 0x7F = 127 ports */ 7862306a36Sopenharmony_ci#define HCS_MAX_PORTS(p) (((p) >> 24) & 0x7f) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* HCSPARAMS2 - hcs_params2 - bitmasks */ 8162306a36Sopenharmony_ci/* bits 0:3, frames or uframes that SW needs to queue transactions 8262306a36Sopenharmony_ci * ahead of the HW to meet periodic deadlines */ 8362306a36Sopenharmony_ci#define HCS_IST(p) (((p) >> 0) & 0xf) 8462306a36Sopenharmony_ci/* bits 4:7, max number of Event Ring segments */ 8562306a36Sopenharmony_ci#define HCS_ERST_MAX(p) (((p) >> 4) & 0xf) 8662306a36Sopenharmony_ci/* bits 21:25 Hi 5 bits of Scratchpad buffers SW must allocate for the HW */ 8762306a36Sopenharmony_ci/* bit 26 Scratchpad restore - for save/restore HW state - not used yet */ 8862306a36Sopenharmony_ci/* bits 27:31 Lo 5 bits of Scratchpad buffers SW must allocate for the HW */ 8962306a36Sopenharmony_ci#define HCS_MAX_SCRATCHPAD(p) ((((p) >> 16) & 0x3e0) | (((p) >> 27) & 0x1f)) 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* HCSPARAMS3 - hcs_params3 - bitmasks */ 9262306a36Sopenharmony_ci/* bits 0:7, Max U1 to U0 latency for the roothub ports */ 9362306a36Sopenharmony_ci#define HCS_U1_LATENCY(p) (((p) >> 0) & 0xff) 9462306a36Sopenharmony_ci/* bits 16:31, Max U2 to U0 latency for the roothub ports */ 9562306a36Sopenharmony_ci#define HCS_U2_LATENCY(p) (((p) >> 16) & 0xffff) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/* HCCPARAMS - hcc_params - bitmasks */ 9862306a36Sopenharmony_ci/* true: HC can use 64-bit address pointers */ 9962306a36Sopenharmony_ci#define HCC_64BIT_ADDR(p) ((p) & (1 << 0)) 10062306a36Sopenharmony_ci/* true: HC can do bandwidth negotiation */ 10162306a36Sopenharmony_ci#define HCC_BANDWIDTH_NEG(p) ((p) & (1 << 1)) 10262306a36Sopenharmony_ci/* true: HC uses 64-byte Device Context structures 10362306a36Sopenharmony_ci * FIXME 64-byte context structures aren't supported yet. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci#define HCC_64BYTE_CONTEXT(p) ((p) & (1 << 2)) 10662306a36Sopenharmony_ci/* true: HC has port power switches */ 10762306a36Sopenharmony_ci#define HCC_PPC(p) ((p) & (1 << 3)) 10862306a36Sopenharmony_ci/* true: HC has port indicators */ 10962306a36Sopenharmony_ci#define HCS_INDICATOR(p) ((p) & (1 << 4)) 11062306a36Sopenharmony_ci/* true: HC has Light HC Reset Capability */ 11162306a36Sopenharmony_ci#define HCC_LIGHT_RESET(p) ((p) & (1 << 5)) 11262306a36Sopenharmony_ci/* true: HC supports latency tolerance messaging */ 11362306a36Sopenharmony_ci#define HCC_LTC(p) ((p) & (1 << 6)) 11462306a36Sopenharmony_ci/* true: no secondary Stream ID Support */ 11562306a36Sopenharmony_ci#define HCC_NSS(p) ((p) & (1 << 7)) 11662306a36Sopenharmony_ci/* true: HC supports Stopped - Short Packet */ 11762306a36Sopenharmony_ci#define HCC_SPC(p) ((p) & (1 << 9)) 11862306a36Sopenharmony_ci/* true: HC has Contiguous Frame ID Capability */ 11962306a36Sopenharmony_ci#define HCC_CFC(p) ((p) & (1 << 11)) 12062306a36Sopenharmony_ci/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */ 12162306a36Sopenharmony_ci#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1)) 12262306a36Sopenharmony_ci/* Extended Capabilities pointer from PCI base - section 5.3.6 */ 12362306a36Sopenharmony_ci#define HCC_EXT_CAPS(p) XHCI_HCC_EXT_CAPS(p) 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32) 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* db_off bitmask - bits 0:1 reserved */ 12862306a36Sopenharmony_ci#define DBOFF_MASK (~0x3) 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/* run_regs_off bitmask - bits 0:4 reserved */ 13162306a36Sopenharmony_ci#define RTSOFF_MASK (~0x1f) 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/* HCCPARAMS2 - hcc_params2 - bitmasks */ 13462306a36Sopenharmony_ci/* true: HC supports U3 entry Capability */ 13562306a36Sopenharmony_ci#define HCC2_U3C(p) ((p) & (1 << 0)) 13662306a36Sopenharmony_ci/* true: HC supports Configure endpoint command Max exit latency too large */ 13762306a36Sopenharmony_ci#define HCC2_CMC(p) ((p) & (1 << 1)) 13862306a36Sopenharmony_ci/* true: HC supports Force Save context Capability */ 13962306a36Sopenharmony_ci#define HCC2_FSC(p) ((p) & (1 << 2)) 14062306a36Sopenharmony_ci/* true: HC supports Compliance Transition Capability */ 14162306a36Sopenharmony_ci#define HCC2_CTC(p) ((p) & (1 << 3)) 14262306a36Sopenharmony_ci/* true: HC support Large ESIT payload Capability > 48k */ 14362306a36Sopenharmony_ci#define HCC2_LEC(p) ((p) & (1 << 4)) 14462306a36Sopenharmony_ci/* true: HC support Configuration Information Capability */ 14562306a36Sopenharmony_ci#define HCC2_CIC(p) ((p) & (1 << 5)) 14662306a36Sopenharmony_ci/* true: HC support Extended TBC Capability, Isoc burst count > 65535 */ 14762306a36Sopenharmony_ci#define HCC2_ETC(p) ((p) & (1 << 6)) 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* Number of registers per port */ 15062306a36Sopenharmony_ci#define NUM_PORT_REGS 4 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci#define PORTSC 0 15362306a36Sopenharmony_ci#define PORTPMSC 1 15462306a36Sopenharmony_ci#define PORTLI 2 15562306a36Sopenharmony_ci#define PORTHLPMC 3 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/** 15862306a36Sopenharmony_ci * struct xhci_op_regs - xHCI Host Controller Operational Registers. 15962306a36Sopenharmony_ci * @command: USBCMD - xHC command register 16062306a36Sopenharmony_ci * @status: USBSTS - xHC status register 16162306a36Sopenharmony_ci * @page_size: This indicates the page size that the host controller 16262306a36Sopenharmony_ci * supports. If bit n is set, the HC supports a page size 16362306a36Sopenharmony_ci * of 2^(n+12), up to a 128MB page size. 16462306a36Sopenharmony_ci * 4K is the minimum page size. 16562306a36Sopenharmony_ci * @cmd_ring: CRP - 64-bit Command Ring Pointer 16662306a36Sopenharmony_ci * @dcbaa_ptr: DCBAAP - 64-bit Device Context Base Address Array Pointer 16762306a36Sopenharmony_ci * @config_reg: CONFIG - Configure Register 16862306a36Sopenharmony_ci * @port_status_base: PORTSCn - base address for Port Status and Control 16962306a36Sopenharmony_ci * Each port has a Port Status and Control register, 17062306a36Sopenharmony_ci * followed by a Port Power Management Status and Control 17162306a36Sopenharmony_ci * register, a Port Link Info register, and a reserved 17262306a36Sopenharmony_ci * register. 17362306a36Sopenharmony_ci * @port_power_base: PORTPMSCn - base address for 17462306a36Sopenharmony_ci * Port Power Management Status and Control 17562306a36Sopenharmony_ci * @port_link_base: PORTLIn - base address for Port Link Info (current 17662306a36Sopenharmony_ci * Link PM state and control) for USB 2.1 and USB 3.0 17762306a36Sopenharmony_ci * devices. 17862306a36Sopenharmony_ci */ 17962306a36Sopenharmony_cistruct xhci_op_regs { 18062306a36Sopenharmony_ci __le32 command; 18162306a36Sopenharmony_ci __le32 status; 18262306a36Sopenharmony_ci __le32 page_size; 18362306a36Sopenharmony_ci __le32 reserved1; 18462306a36Sopenharmony_ci __le32 reserved2; 18562306a36Sopenharmony_ci __le32 dev_notification; 18662306a36Sopenharmony_ci __le64 cmd_ring; 18762306a36Sopenharmony_ci /* rsvd: offset 0x20-2F */ 18862306a36Sopenharmony_ci __le32 reserved3[4]; 18962306a36Sopenharmony_ci __le64 dcbaa_ptr; 19062306a36Sopenharmony_ci __le32 config_reg; 19162306a36Sopenharmony_ci /* rsvd: offset 0x3C-3FF */ 19262306a36Sopenharmony_ci __le32 reserved4[241]; 19362306a36Sopenharmony_ci /* port 1 registers, which serve as a base address for other ports */ 19462306a36Sopenharmony_ci __le32 port_status_base; 19562306a36Sopenharmony_ci __le32 port_power_base; 19662306a36Sopenharmony_ci __le32 port_link_base; 19762306a36Sopenharmony_ci __le32 reserved5; 19862306a36Sopenharmony_ci /* registers for ports 2-255 */ 19962306a36Sopenharmony_ci __le32 reserved6[NUM_PORT_REGS*254]; 20062306a36Sopenharmony_ci}; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* USBCMD - USB command - command bitmasks */ 20362306a36Sopenharmony_ci/* start/stop HC execution - do not write unless HC is halted*/ 20462306a36Sopenharmony_ci#define CMD_RUN XHCI_CMD_RUN 20562306a36Sopenharmony_ci/* Reset HC - resets internal HC state machine and all registers (except 20662306a36Sopenharmony_ci * PCI config regs). HC does NOT drive a USB reset on the downstream ports. 20762306a36Sopenharmony_ci * The xHCI driver must reinitialize the xHC after setting this bit. 20862306a36Sopenharmony_ci */ 20962306a36Sopenharmony_ci#define CMD_RESET (1 << 1) 21062306a36Sopenharmony_ci/* Event Interrupt Enable - a '1' allows interrupts from the host controller */ 21162306a36Sopenharmony_ci#define CMD_EIE XHCI_CMD_EIE 21262306a36Sopenharmony_ci/* Host System Error Interrupt Enable - get out-of-band signal for HC errors */ 21362306a36Sopenharmony_ci#define CMD_HSEIE XHCI_CMD_HSEIE 21462306a36Sopenharmony_ci/* bits 4:6 are reserved (and should be preserved on writes). */ 21562306a36Sopenharmony_ci/* light reset (port status stays unchanged) - reset completed when this is 0 */ 21662306a36Sopenharmony_ci#define CMD_LRESET (1 << 7) 21762306a36Sopenharmony_ci/* host controller save/restore state. */ 21862306a36Sopenharmony_ci#define CMD_CSS (1 << 8) 21962306a36Sopenharmony_ci#define CMD_CRS (1 << 9) 22062306a36Sopenharmony_ci/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ 22162306a36Sopenharmony_ci#define CMD_EWE XHCI_CMD_EWE 22262306a36Sopenharmony_ci/* MFINDEX power management - '1' means xHC can stop MFINDEX counter if all root 22362306a36Sopenharmony_ci * hubs are in U3 (selective suspend), disconnect, disabled, or powered-off. 22462306a36Sopenharmony_ci * '0' means the xHC can power it off if all ports are in the disconnect, 22562306a36Sopenharmony_ci * disabled, or powered-off state. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ci#define CMD_PM_INDEX (1 << 11) 22862306a36Sopenharmony_ci/* bit 14 Extended TBC Enable, changes Isoc TRB fields to support larger TBC */ 22962306a36Sopenharmony_ci#define CMD_ETE (1 << 14) 23062306a36Sopenharmony_ci/* bits 15:31 are reserved (and should be preserved on writes). */ 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci#define XHCI_RESET_LONG_USEC (10 * 1000 * 1000) 23362306a36Sopenharmony_ci#define XHCI_RESET_SHORT_USEC (250 * 1000) 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci/* IMAN - Interrupt Management Register */ 23662306a36Sopenharmony_ci#define IMAN_IE (1 << 1) 23762306a36Sopenharmony_ci#define IMAN_IP (1 << 0) 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci/* USBSTS - USB status - status bitmasks */ 24062306a36Sopenharmony_ci/* HC not running - set to 1 when run/stop bit is cleared. */ 24162306a36Sopenharmony_ci#define STS_HALT XHCI_STS_HALT 24262306a36Sopenharmony_ci/* serious error, e.g. PCI parity error. The HC will clear the run/stop bit. */ 24362306a36Sopenharmony_ci#define STS_FATAL (1 << 2) 24462306a36Sopenharmony_ci/* event interrupt - clear this prior to clearing any IP flags in IR set*/ 24562306a36Sopenharmony_ci#define STS_EINT (1 << 3) 24662306a36Sopenharmony_ci/* port change detect */ 24762306a36Sopenharmony_ci#define STS_PORT (1 << 4) 24862306a36Sopenharmony_ci/* bits 5:7 reserved and zeroed */ 24962306a36Sopenharmony_ci/* save state status - '1' means xHC is saving state */ 25062306a36Sopenharmony_ci#define STS_SAVE (1 << 8) 25162306a36Sopenharmony_ci/* restore state status - '1' means xHC is restoring state */ 25262306a36Sopenharmony_ci#define STS_RESTORE (1 << 9) 25362306a36Sopenharmony_ci/* true: save or restore error */ 25462306a36Sopenharmony_ci#define STS_SRE (1 << 10) 25562306a36Sopenharmony_ci/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ 25662306a36Sopenharmony_ci#define STS_CNR XHCI_STS_CNR 25762306a36Sopenharmony_ci/* true: internal Host Controller Error - SW needs to reset and reinitialize */ 25862306a36Sopenharmony_ci#define STS_HCE (1 << 12) 25962306a36Sopenharmony_ci/* bits 13:31 reserved and should be preserved */ 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/* 26262306a36Sopenharmony_ci * DNCTRL - Device Notification Control Register - dev_notification bitmasks 26362306a36Sopenharmony_ci * Generate a device notification event when the HC sees a transaction with a 26462306a36Sopenharmony_ci * notification type that matches a bit set in this bit field. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci#define DEV_NOTE_MASK (0xffff) 26762306a36Sopenharmony_ci#define ENABLE_DEV_NOTE(x) (1 << (x)) 26862306a36Sopenharmony_ci/* Most of the device notification types should only be used for debug. 26962306a36Sopenharmony_ci * SW does need to pay attention to function wake notifications. 27062306a36Sopenharmony_ci */ 27162306a36Sopenharmony_ci#define DEV_NOTE_FWAKE ENABLE_DEV_NOTE(1) 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/* CRCR - Command Ring Control Register - cmd_ring bitmasks */ 27462306a36Sopenharmony_ci/* bit 0 is the command ring cycle state */ 27562306a36Sopenharmony_ci/* stop ring operation after completion of the currently executing command */ 27662306a36Sopenharmony_ci#define CMD_RING_PAUSE (1 << 1) 27762306a36Sopenharmony_ci/* stop ring immediately - abort the currently executing command */ 27862306a36Sopenharmony_ci#define CMD_RING_ABORT (1 << 2) 27962306a36Sopenharmony_ci/* true: command ring is running */ 28062306a36Sopenharmony_ci#define CMD_RING_RUNNING (1 << 3) 28162306a36Sopenharmony_ci/* bits 4:5 reserved and should be preserved */ 28262306a36Sopenharmony_ci/* Command Ring pointer - bit mask for the lower 32 bits. */ 28362306a36Sopenharmony_ci#define CMD_RING_RSVD_BITS (0x3f) 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci/* CONFIG - Configure Register - config_reg bitmasks */ 28662306a36Sopenharmony_ci/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */ 28762306a36Sopenharmony_ci#define MAX_DEVS(p) ((p) & 0xff) 28862306a36Sopenharmony_ci/* bit 8: U3 Entry Enabled, assert PLC when root port enters U3, xhci 1.1 */ 28962306a36Sopenharmony_ci#define CONFIG_U3E (1 << 8) 29062306a36Sopenharmony_ci/* bit 9: Configuration Information Enable, xhci 1.1 */ 29162306a36Sopenharmony_ci#define CONFIG_CIE (1 << 9) 29262306a36Sopenharmony_ci/* bits 10:31 - reserved and should be preserved */ 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/* PORTSC - Port Status and Control Register - port_status_base bitmasks */ 29562306a36Sopenharmony_ci/* true: device connected */ 29662306a36Sopenharmony_ci#define PORT_CONNECT (1 << 0) 29762306a36Sopenharmony_ci/* true: port enabled */ 29862306a36Sopenharmony_ci#define PORT_PE (1 << 1) 29962306a36Sopenharmony_ci/* bit 2 reserved and zeroed */ 30062306a36Sopenharmony_ci/* true: port has an over-current condition */ 30162306a36Sopenharmony_ci#define PORT_OC (1 << 3) 30262306a36Sopenharmony_ci/* true: port reset signaling asserted */ 30362306a36Sopenharmony_ci#define PORT_RESET (1 << 4) 30462306a36Sopenharmony_ci/* Port Link State - bits 5:8 30562306a36Sopenharmony_ci * A read gives the current link PM state of the port, 30662306a36Sopenharmony_ci * a write with Link State Write Strobe set sets the link state. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci#define PORT_PLS_MASK (0xf << 5) 30962306a36Sopenharmony_ci#define XDEV_U0 (0x0 << 5) 31062306a36Sopenharmony_ci#define XDEV_U1 (0x1 << 5) 31162306a36Sopenharmony_ci#define XDEV_U2 (0x2 << 5) 31262306a36Sopenharmony_ci#define XDEV_U3 (0x3 << 5) 31362306a36Sopenharmony_ci#define XDEV_DISABLED (0x4 << 5) 31462306a36Sopenharmony_ci#define XDEV_RXDETECT (0x5 << 5) 31562306a36Sopenharmony_ci#define XDEV_INACTIVE (0x6 << 5) 31662306a36Sopenharmony_ci#define XDEV_POLLING (0x7 << 5) 31762306a36Sopenharmony_ci#define XDEV_RECOVERY (0x8 << 5) 31862306a36Sopenharmony_ci#define XDEV_HOT_RESET (0x9 << 5) 31962306a36Sopenharmony_ci#define XDEV_COMP_MODE (0xa << 5) 32062306a36Sopenharmony_ci#define XDEV_TEST_MODE (0xb << 5) 32162306a36Sopenharmony_ci#define XDEV_RESUME (0xf << 5) 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/* true: port has power (see HCC_PPC) */ 32462306a36Sopenharmony_ci#define PORT_POWER (1 << 9) 32562306a36Sopenharmony_ci/* bits 10:13 indicate device speed: 32662306a36Sopenharmony_ci * 0 - undefined speed - port hasn't be initialized by a reset yet 32762306a36Sopenharmony_ci * 1 - full speed 32862306a36Sopenharmony_ci * 2 - low speed 32962306a36Sopenharmony_ci * 3 - high speed 33062306a36Sopenharmony_ci * 4 - super speed 33162306a36Sopenharmony_ci * 5-15 reserved 33262306a36Sopenharmony_ci */ 33362306a36Sopenharmony_ci#define DEV_SPEED_MASK (0xf << 10) 33462306a36Sopenharmony_ci#define XDEV_FS (0x1 << 10) 33562306a36Sopenharmony_ci#define XDEV_LS (0x2 << 10) 33662306a36Sopenharmony_ci#define XDEV_HS (0x3 << 10) 33762306a36Sopenharmony_ci#define XDEV_SS (0x4 << 10) 33862306a36Sopenharmony_ci#define XDEV_SSP (0x5 << 10) 33962306a36Sopenharmony_ci#define DEV_UNDEFSPEED(p) (((p) & DEV_SPEED_MASK) == (0x0<<10)) 34062306a36Sopenharmony_ci#define DEV_FULLSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_FS) 34162306a36Sopenharmony_ci#define DEV_LOWSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_LS) 34262306a36Sopenharmony_ci#define DEV_HIGHSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_HS) 34362306a36Sopenharmony_ci#define DEV_SUPERSPEED(p) (((p) & DEV_SPEED_MASK) == XDEV_SS) 34462306a36Sopenharmony_ci#define DEV_SUPERSPEEDPLUS(p) (((p) & DEV_SPEED_MASK) == XDEV_SSP) 34562306a36Sopenharmony_ci#define DEV_SUPERSPEED_ANY(p) (((p) & DEV_SPEED_MASK) >= XDEV_SS) 34662306a36Sopenharmony_ci#define DEV_PORT_SPEED(p) (((p) >> 10) & 0x0f) 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci/* Bits 20:23 in the Slot Context are the speed for the device */ 34962306a36Sopenharmony_ci#define SLOT_SPEED_FS (XDEV_FS << 10) 35062306a36Sopenharmony_ci#define SLOT_SPEED_LS (XDEV_LS << 10) 35162306a36Sopenharmony_ci#define SLOT_SPEED_HS (XDEV_HS << 10) 35262306a36Sopenharmony_ci#define SLOT_SPEED_SS (XDEV_SS << 10) 35362306a36Sopenharmony_ci#define SLOT_SPEED_SSP (XDEV_SSP << 10) 35462306a36Sopenharmony_ci/* Port Indicator Control */ 35562306a36Sopenharmony_ci#define PORT_LED_OFF (0 << 14) 35662306a36Sopenharmony_ci#define PORT_LED_AMBER (1 << 14) 35762306a36Sopenharmony_ci#define PORT_LED_GREEN (2 << 14) 35862306a36Sopenharmony_ci#define PORT_LED_MASK (3 << 14) 35962306a36Sopenharmony_ci/* Port Link State Write Strobe - set this when changing link state */ 36062306a36Sopenharmony_ci#define PORT_LINK_STROBE (1 << 16) 36162306a36Sopenharmony_ci/* true: connect status change */ 36262306a36Sopenharmony_ci#define PORT_CSC (1 << 17) 36362306a36Sopenharmony_ci/* true: port enable change */ 36462306a36Sopenharmony_ci#define PORT_PEC (1 << 18) 36562306a36Sopenharmony_ci/* true: warm reset for a USB 3.0 device is done. A "hot" reset puts the port 36662306a36Sopenharmony_ci * into an enabled state, and the device into the default state. A "warm" reset 36762306a36Sopenharmony_ci * also resets the link, forcing the device through the link training sequence. 36862306a36Sopenharmony_ci * SW can also look at the Port Reset register to see when warm reset is done. 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ci#define PORT_WRC (1 << 19) 37162306a36Sopenharmony_ci/* true: over-current change */ 37262306a36Sopenharmony_ci#define PORT_OCC (1 << 20) 37362306a36Sopenharmony_ci/* true: reset change - 1 to 0 transition of PORT_RESET */ 37462306a36Sopenharmony_ci#define PORT_RC (1 << 21) 37562306a36Sopenharmony_ci/* port link status change - set on some port link state transitions: 37662306a36Sopenharmony_ci * Transition Reason 37762306a36Sopenharmony_ci * ------------------------------------------------------------------------------ 37862306a36Sopenharmony_ci * - U3 to Resume Wakeup signaling from a device 37962306a36Sopenharmony_ci * - Resume to Recovery to U0 USB 3.0 device resume 38062306a36Sopenharmony_ci * - Resume to U0 USB 2.0 device resume 38162306a36Sopenharmony_ci * - U3 to Recovery to U0 Software resume of USB 3.0 device complete 38262306a36Sopenharmony_ci * - U3 to U0 Software resume of USB 2.0 device complete 38362306a36Sopenharmony_ci * - U2 to U0 L1 resume of USB 2.1 device complete 38462306a36Sopenharmony_ci * - U0 to U0 (???) L1 entry rejection by USB 2.1 device 38562306a36Sopenharmony_ci * - U0 to disabled L1 entry error with USB 2.1 device 38662306a36Sopenharmony_ci * - Any state to inactive Error on USB 3.0 port 38762306a36Sopenharmony_ci */ 38862306a36Sopenharmony_ci#define PORT_PLC (1 << 22) 38962306a36Sopenharmony_ci/* port configure error change - port failed to configure its link partner */ 39062306a36Sopenharmony_ci#define PORT_CEC (1 << 23) 39162306a36Sopenharmony_ci#define PORT_CHANGE_MASK (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ 39262306a36Sopenharmony_ci PORT_RC | PORT_PLC | PORT_CEC) 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci/* Cold Attach Status - xHC can set this bit to report device attached during 39662306a36Sopenharmony_ci * Sx state. Warm port reset should be perfomed to clear this bit and move port 39762306a36Sopenharmony_ci * to connected state. 39862306a36Sopenharmony_ci */ 39962306a36Sopenharmony_ci#define PORT_CAS (1 << 24) 40062306a36Sopenharmony_ci/* wake on connect (enable) */ 40162306a36Sopenharmony_ci#define PORT_WKCONN_E (1 << 25) 40262306a36Sopenharmony_ci/* wake on disconnect (enable) */ 40362306a36Sopenharmony_ci#define PORT_WKDISC_E (1 << 26) 40462306a36Sopenharmony_ci/* wake on over-current (enable) */ 40562306a36Sopenharmony_ci#define PORT_WKOC_E (1 << 27) 40662306a36Sopenharmony_ci/* bits 28:29 reserved */ 40762306a36Sopenharmony_ci/* true: device is non-removable - for USB 3.0 roothub emulation */ 40862306a36Sopenharmony_ci#define PORT_DEV_REMOVE (1 << 30) 40962306a36Sopenharmony_ci/* Initiate a warm port reset - complete when PORT_WRC is '1' */ 41062306a36Sopenharmony_ci#define PORT_WR (1 << 31) 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci/* We mark duplicate entries with -1 */ 41362306a36Sopenharmony_ci#define DUPLICATE_ENTRY ((u8)(-1)) 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/* Port Power Management Status and Control - port_power_base bitmasks */ 41662306a36Sopenharmony_ci/* Inactivity timer value for transitions into U1, in microseconds. 41762306a36Sopenharmony_ci * Timeout can be up to 127us. 0xFF means an infinite timeout. 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci#define PORT_U1_TIMEOUT(p) ((p) & 0xff) 42062306a36Sopenharmony_ci#define PORT_U1_TIMEOUT_MASK 0xff 42162306a36Sopenharmony_ci/* Inactivity timer value for transitions into U2 */ 42262306a36Sopenharmony_ci#define PORT_U2_TIMEOUT(p) (((p) & 0xff) << 8) 42362306a36Sopenharmony_ci#define PORT_U2_TIMEOUT_MASK (0xff << 8) 42462306a36Sopenharmony_ci/* Bits 24:31 for port testing */ 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci/* USB2 Protocol PORTSPMSC */ 42762306a36Sopenharmony_ci#define PORT_L1S_MASK 7 42862306a36Sopenharmony_ci#define PORT_L1S_SUCCESS 1 42962306a36Sopenharmony_ci#define PORT_RWE (1 << 3) 43062306a36Sopenharmony_ci#define PORT_HIRD(p) (((p) & 0xf) << 4) 43162306a36Sopenharmony_ci#define PORT_HIRD_MASK (0xf << 4) 43262306a36Sopenharmony_ci#define PORT_L1DS_MASK (0xff << 8) 43362306a36Sopenharmony_ci#define PORT_L1DS(p) (((p) & 0xff) << 8) 43462306a36Sopenharmony_ci#define PORT_HLE (1 << 16) 43562306a36Sopenharmony_ci#define PORT_TEST_MODE_SHIFT 28 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci/* USB3 Protocol PORTLI Port Link Information */ 43862306a36Sopenharmony_ci#define PORT_RX_LANES(p) (((p) >> 16) & 0xf) 43962306a36Sopenharmony_ci#define PORT_TX_LANES(p) (((p) >> 20) & 0xf) 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci/* USB2 Protocol PORTHLPMC */ 44262306a36Sopenharmony_ci#define PORT_HIRDM(p)((p) & 3) 44362306a36Sopenharmony_ci#define PORT_L1_TIMEOUT(p)(((p) & 0xff) << 2) 44462306a36Sopenharmony_ci#define PORT_BESLD(p)(((p) & 0xf) << 10) 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/* use 512 microseconds as USB2 LPM L1 default timeout. */ 44762306a36Sopenharmony_ci#define XHCI_L1_TIMEOUT 512 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci/* Set default HIRD/BESL value to 4 (350/400us) for USB2 L1 LPM resume latency. 45062306a36Sopenharmony_ci * Safe to use with mixed HIRD and BESL systems (host and device) and is used 45162306a36Sopenharmony_ci * by other operating systems. 45262306a36Sopenharmony_ci * 45362306a36Sopenharmony_ci * XHCI 1.0 errata 8/14/12 Table 13 notes: 45462306a36Sopenharmony_ci * "Software should choose xHC BESL/BESLD field values that do not violate a 45562306a36Sopenharmony_ci * device's resume latency requirements, 45662306a36Sopenharmony_ci * e.g. not program values > '4' if BLC = '1' and a HIRD device is attached, 45762306a36Sopenharmony_ci * or not program values < '4' if BLC = '0' and a BESL device is attached. 45862306a36Sopenharmony_ci */ 45962306a36Sopenharmony_ci#define XHCI_DEFAULT_BESL 4 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci/* 46262306a36Sopenharmony_ci * USB3 specification define a 360ms tPollingLFPSTiemout for USB3 ports 46362306a36Sopenharmony_ci * to complete link training. usually link trainig completes much faster 46462306a36Sopenharmony_ci * so check status 10 times with 36ms sleep in places we need to wait for 46562306a36Sopenharmony_ci * polling to complete. 46662306a36Sopenharmony_ci */ 46762306a36Sopenharmony_ci#define XHCI_PORT_POLLING_LFPS_TIME 36 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci/** 47062306a36Sopenharmony_ci * struct xhci_intr_reg - Interrupt Register Set 47162306a36Sopenharmony_ci * @irq_pending: IMAN - Interrupt Management Register. Used to enable 47262306a36Sopenharmony_ci * interrupts and check for pending interrupts. 47362306a36Sopenharmony_ci * @irq_control: IMOD - Interrupt Moderation Register. 47462306a36Sopenharmony_ci * Used to throttle interrupts. 47562306a36Sopenharmony_ci * @erst_size: Number of segments in the Event Ring Segment Table (ERST). 47662306a36Sopenharmony_ci * @erst_base: ERST base address. 47762306a36Sopenharmony_ci * @erst_dequeue: Event ring dequeue pointer. 47862306a36Sopenharmony_ci * 47962306a36Sopenharmony_ci * Each interrupter (defined by a MSI-X vector) has an event ring and an Event 48062306a36Sopenharmony_ci * Ring Segment Table (ERST) associated with it. The event ring is comprised of 48162306a36Sopenharmony_ci * multiple segments of the same size. The HC places events on the ring and 48262306a36Sopenharmony_ci * "updates the Cycle bit in the TRBs to indicate to software the current 48362306a36Sopenharmony_ci * position of the Enqueue Pointer." The HCD (Linux) processes those events and 48462306a36Sopenharmony_ci * updates the dequeue pointer. 48562306a36Sopenharmony_ci */ 48662306a36Sopenharmony_cistruct xhci_intr_reg { 48762306a36Sopenharmony_ci __le32 irq_pending; 48862306a36Sopenharmony_ci __le32 irq_control; 48962306a36Sopenharmony_ci __le32 erst_size; 49062306a36Sopenharmony_ci __le32 rsvd; 49162306a36Sopenharmony_ci __le64 erst_base; 49262306a36Sopenharmony_ci __le64 erst_dequeue; 49362306a36Sopenharmony_ci}; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci/* irq_pending bitmasks */ 49662306a36Sopenharmony_ci#define ER_IRQ_PENDING(p) ((p) & 0x1) 49762306a36Sopenharmony_ci/* bits 2:31 need to be preserved */ 49862306a36Sopenharmony_ci/* THIS IS BUGGY - FIXME - IP IS WRITE 1 TO CLEAR */ 49962306a36Sopenharmony_ci#define ER_IRQ_CLEAR(p) ((p) & 0xfffffffe) 50062306a36Sopenharmony_ci#define ER_IRQ_ENABLE(p) ((ER_IRQ_CLEAR(p)) | 0x2) 50162306a36Sopenharmony_ci#define ER_IRQ_DISABLE(p) ((ER_IRQ_CLEAR(p)) & ~(0x2)) 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci/* irq_control bitmasks */ 50462306a36Sopenharmony_ci/* Minimum interval between interrupts (in 250ns intervals). The interval 50562306a36Sopenharmony_ci * between interrupts will be longer if there are no events on the event ring. 50662306a36Sopenharmony_ci * Default is 4000 (1 ms). 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_ci#define ER_IRQ_INTERVAL_MASK (0xffff) 50962306a36Sopenharmony_ci/* Counter used to count down the time to the next interrupt - HW use only */ 51062306a36Sopenharmony_ci#define ER_IRQ_COUNTER_MASK (0xffff << 16) 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci/* erst_size bitmasks */ 51362306a36Sopenharmony_ci/* Preserve bits 16:31 of erst_size */ 51462306a36Sopenharmony_ci#define ERST_SIZE_MASK (0xffff << 16) 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci/* erst_base bitmasks */ 51762306a36Sopenharmony_ci#define ERST_BASE_RSVDP (GENMASK_ULL(5, 0)) 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci/* erst_dequeue bitmasks */ 52062306a36Sopenharmony_ci/* Dequeue ERST Segment Index (DESI) - Segment number (or alias) 52162306a36Sopenharmony_ci * where the current dequeue pointer lies. This is an optional HW hint. 52262306a36Sopenharmony_ci */ 52362306a36Sopenharmony_ci#define ERST_DESI_MASK (0x7) 52462306a36Sopenharmony_ci/* Event Handler Busy (EHB) - is the event ring scheduled to be serviced by 52562306a36Sopenharmony_ci * a work queue (or delayed service routine)? 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_ci#define ERST_EHB (1 << 3) 52862306a36Sopenharmony_ci#define ERST_PTR_MASK (0xf) 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/** 53162306a36Sopenharmony_ci * struct xhci_run_regs 53262306a36Sopenharmony_ci * @microframe_index: 53362306a36Sopenharmony_ci * MFINDEX - current microframe number 53462306a36Sopenharmony_ci * 53562306a36Sopenharmony_ci * Section 5.5 Host Controller Runtime Registers: 53662306a36Sopenharmony_ci * "Software should read and write these registers using only Dword (32 bit) 53762306a36Sopenharmony_ci * or larger accesses" 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_cistruct xhci_run_regs { 54062306a36Sopenharmony_ci __le32 microframe_index; 54162306a36Sopenharmony_ci __le32 rsvd[7]; 54262306a36Sopenharmony_ci struct xhci_intr_reg ir_set[128]; 54362306a36Sopenharmony_ci}; 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci/** 54662306a36Sopenharmony_ci * struct doorbell_array 54762306a36Sopenharmony_ci * 54862306a36Sopenharmony_ci * Bits 0 - 7: Endpoint target 54962306a36Sopenharmony_ci * Bits 8 - 15: RsvdZ 55062306a36Sopenharmony_ci * Bits 16 - 31: Stream ID 55162306a36Sopenharmony_ci * 55262306a36Sopenharmony_ci * Section 5.6 55362306a36Sopenharmony_ci */ 55462306a36Sopenharmony_cistruct xhci_doorbell_array { 55562306a36Sopenharmony_ci __le32 doorbell[256]; 55662306a36Sopenharmony_ci}; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16)) 55962306a36Sopenharmony_ci#define DB_VALUE_HOST 0x00000000 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci/** 56262306a36Sopenharmony_ci * struct xhci_protocol_caps 56362306a36Sopenharmony_ci * @revision: major revision, minor revision, capability ID, 56462306a36Sopenharmony_ci * and next capability pointer. 56562306a36Sopenharmony_ci * @name_string: Four ASCII characters to say which spec this xHC 56662306a36Sopenharmony_ci * follows, typically "USB ". 56762306a36Sopenharmony_ci * @port_info: Port offset, count, and protocol-defined information. 56862306a36Sopenharmony_ci */ 56962306a36Sopenharmony_cistruct xhci_protocol_caps { 57062306a36Sopenharmony_ci u32 revision; 57162306a36Sopenharmony_ci u32 name_string; 57262306a36Sopenharmony_ci u32 port_info; 57362306a36Sopenharmony_ci}; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) 57662306a36Sopenharmony_ci#define XHCI_EXT_PORT_MINOR(x) (((x) >> 16) & 0xff) 57762306a36Sopenharmony_ci#define XHCI_EXT_PORT_PSIC(x) (((x) >> 28) & 0x0f) 57862306a36Sopenharmony_ci#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) 57962306a36Sopenharmony_ci#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci#define XHCI_EXT_PORT_PSIV(x) (((x) >> 0) & 0x0f) 58262306a36Sopenharmony_ci#define XHCI_EXT_PORT_PSIE(x) (((x) >> 4) & 0x03) 58362306a36Sopenharmony_ci#define XHCI_EXT_PORT_PLT(x) (((x) >> 6) & 0x03) 58462306a36Sopenharmony_ci#define XHCI_EXT_PORT_PFD(x) (((x) >> 8) & 0x01) 58562306a36Sopenharmony_ci#define XHCI_EXT_PORT_LP(x) (((x) >> 14) & 0x03) 58662306a36Sopenharmony_ci#define XHCI_EXT_PORT_PSIM(x) (((x) >> 16) & 0xffff) 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci#define PLT_MASK (0x03 << 6) 58962306a36Sopenharmony_ci#define PLT_SYM (0x00 << 6) 59062306a36Sopenharmony_ci#define PLT_ASYM_RX (0x02 << 6) 59162306a36Sopenharmony_ci#define PLT_ASYM_TX (0x03 << 6) 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci/** 59462306a36Sopenharmony_ci * struct xhci_container_ctx 59562306a36Sopenharmony_ci * @type: Type of context. Used to calculated offsets to contained contexts. 59662306a36Sopenharmony_ci * @size: Size of the context data 59762306a36Sopenharmony_ci * @bytes: The raw context data given to HW 59862306a36Sopenharmony_ci * @dma: dma address of the bytes 59962306a36Sopenharmony_ci * 60062306a36Sopenharmony_ci * Represents either a Device or Input context. Holds a pointer to the raw 60162306a36Sopenharmony_ci * memory used for the context (bytes) and dma address of it (dma). 60262306a36Sopenharmony_ci */ 60362306a36Sopenharmony_cistruct xhci_container_ctx { 60462306a36Sopenharmony_ci unsigned type; 60562306a36Sopenharmony_ci#define XHCI_CTX_TYPE_DEVICE 0x1 60662306a36Sopenharmony_ci#define XHCI_CTX_TYPE_INPUT 0x2 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci int size; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci u8 *bytes; 61162306a36Sopenharmony_ci dma_addr_t dma; 61262306a36Sopenharmony_ci}; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci/** 61562306a36Sopenharmony_ci * struct xhci_slot_ctx 61662306a36Sopenharmony_ci * @dev_info: Route string, device speed, hub info, and last valid endpoint 61762306a36Sopenharmony_ci * @dev_info2: Max exit latency for device number, root hub port number 61862306a36Sopenharmony_ci * @tt_info: tt_info is used to construct split transaction tokens 61962306a36Sopenharmony_ci * @dev_state: slot state and device address 62062306a36Sopenharmony_ci * 62162306a36Sopenharmony_ci * Slot Context - section 6.2.1.1. This assumes the HC uses 32-byte context 62262306a36Sopenharmony_ci * structures. If the HC uses 64-byte contexts, there is an additional 32 bytes 62362306a36Sopenharmony_ci * reserved at the end of the slot context for HC internal use. 62462306a36Sopenharmony_ci */ 62562306a36Sopenharmony_cistruct xhci_slot_ctx { 62662306a36Sopenharmony_ci __le32 dev_info; 62762306a36Sopenharmony_ci __le32 dev_info2; 62862306a36Sopenharmony_ci __le32 tt_info; 62962306a36Sopenharmony_ci __le32 dev_state; 63062306a36Sopenharmony_ci /* offset 0x10 to 0x1f reserved for HC internal use */ 63162306a36Sopenharmony_ci __le32 reserved[4]; 63262306a36Sopenharmony_ci}; 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci/* dev_info bitmasks */ 63562306a36Sopenharmony_ci/* Route String - 0:19 */ 63662306a36Sopenharmony_ci#define ROUTE_STRING_MASK (0xfffff) 63762306a36Sopenharmony_ci/* Device speed - values defined by PORTSC Device Speed field - 20:23 */ 63862306a36Sopenharmony_ci#define DEV_SPEED (0xf << 20) 63962306a36Sopenharmony_ci#define GET_DEV_SPEED(n) (((n) & DEV_SPEED) >> 20) 64062306a36Sopenharmony_ci/* bit 24 reserved */ 64162306a36Sopenharmony_ci/* Is this LS/FS device connected through a HS hub? - bit 25 */ 64262306a36Sopenharmony_ci#define DEV_MTT (0x1 << 25) 64362306a36Sopenharmony_ci/* Set if the device is a hub - bit 26 */ 64462306a36Sopenharmony_ci#define DEV_HUB (0x1 << 26) 64562306a36Sopenharmony_ci/* Index of the last valid endpoint context in this device context - 27:31 */ 64662306a36Sopenharmony_ci#define LAST_CTX_MASK (0x1f << 27) 64762306a36Sopenharmony_ci#define LAST_CTX(p) ((p) << 27) 64862306a36Sopenharmony_ci#define LAST_CTX_TO_EP_NUM(p) (((p) >> 27) - 1) 64962306a36Sopenharmony_ci#define SLOT_FLAG (1 << 0) 65062306a36Sopenharmony_ci#define EP0_FLAG (1 << 1) 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci/* dev_info2 bitmasks */ 65362306a36Sopenharmony_ci/* Max Exit Latency (ms) - worst case time to wake up all links in dev path */ 65462306a36Sopenharmony_ci#define MAX_EXIT (0xffff) 65562306a36Sopenharmony_ci/* Root hub port number that is needed to access the USB device */ 65662306a36Sopenharmony_ci#define ROOT_HUB_PORT(p) (((p) & 0xff) << 16) 65762306a36Sopenharmony_ci#define DEVINFO_TO_ROOT_HUB_PORT(p) (((p) >> 16) & 0xff) 65862306a36Sopenharmony_ci/* Maximum number of ports under a hub device */ 65962306a36Sopenharmony_ci#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) 66062306a36Sopenharmony_ci#define DEVINFO_TO_MAX_PORTS(p) (((p) & (0xff << 24)) >> 24) 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci/* tt_info bitmasks */ 66362306a36Sopenharmony_ci/* 66462306a36Sopenharmony_ci * TT Hub Slot ID - for low or full speed devices attached to a high-speed hub 66562306a36Sopenharmony_ci * The Slot ID of the hub that isolates the high speed signaling from 66662306a36Sopenharmony_ci * this low or full-speed device. '0' if attached to root hub port. 66762306a36Sopenharmony_ci */ 66862306a36Sopenharmony_ci#define TT_SLOT (0xff) 66962306a36Sopenharmony_ci/* 67062306a36Sopenharmony_ci * The number of the downstream facing port of the high-speed hub 67162306a36Sopenharmony_ci * '0' if the device is not low or full speed. 67262306a36Sopenharmony_ci */ 67362306a36Sopenharmony_ci#define TT_PORT (0xff << 8) 67462306a36Sopenharmony_ci#define TT_THINK_TIME(p) (((p) & 0x3) << 16) 67562306a36Sopenharmony_ci#define GET_TT_THINK_TIME(p) (((p) & (0x3 << 16)) >> 16) 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci/* dev_state bitmasks */ 67862306a36Sopenharmony_ci/* USB device address - assigned by the HC */ 67962306a36Sopenharmony_ci#define DEV_ADDR_MASK (0xff) 68062306a36Sopenharmony_ci/* bits 8:26 reserved */ 68162306a36Sopenharmony_ci/* Slot state */ 68262306a36Sopenharmony_ci#define SLOT_STATE (0x1f << 27) 68362306a36Sopenharmony_ci#define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27) 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci#define SLOT_STATE_DISABLED 0 68662306a36Sopenharmony_ci#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED 68762306a36Sopenharmony_ci#define SLOT_STATE_DEFAULT 1 68862306a36Sopenharmony_ci#define SLOT_STATE_ADDRESSED 2 68962306a36Sopenharmony_ci#define SLOT_STATE_CONFIGURED 3 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci/** 69262306a36Sopenharmony_ci * struct xhci_ep_ctx 69362306a36Sopenharmony_ci * @ep_info: endpoint state, streams, mult, and interval information. 69462306a36Sopenharmony_ci * @ep_info2: information on endpoint type, max packet size, max burst size, 69562306a36Sopenharmony_ci * error count, and whether the HC will force an event for all 69662306a36Sopenharmony_ci * transactions. 69762306a36Sopenharmony_ci * @deq: 64-bit ring dequeue pointer address. If the endpoint only 69862306a36Sopenharmony_ci * defines one stream, this points to the endpoint transfer ring. 69962306a36Sopenharmony_ci * Otherwise, it points to a stream context array, which has a 70062306a36Sopenharmony_ci * ring pointer for each flow. 70162306a36Sopenharmony_ci * @tx_info: 70262306a36Sopenharmony_ci * Average TRB lengths for the endpoint ring and 70362306a36Sopenharmony_ci * max payload within an Endpoint Service Interval Time (ESIT). 70462306a36Sopenharmony_ci * 70562306a36Sopenharmony_ci * Endpoint Context - section 6.2.1.2. This assumes the HC uses 32-byte context 70662306a36Sopenharmony_ci * structures. If the HC uses 64-byte contexts, there is an additional 32 bytes 70762306a36Sopenharmony_ci * reserved at the end of the endpoint context for HC internal use. 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_cistruct xhci_ep_ctx { 71062306a36Sopenharmony_ci __le32 ep_info; 71162306a36Sopenharmony_ci __le32 ep_info2; 71262306a36Sopenharmony_ci __le64 deq; 71362306a36Sopenharmony_ci __le32 tx_info; 71462306a36Sopenharmony_ci /* offset 0x14 - 0x1f reserved for HC internal use */ 71562306a36Sopenharmony_ci __le32 reserved[3]; 71662306a36Sopenharmony_ci}; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci/* ep_info bitmasks */ 71962306a36Sopenharmony_ci/* 72062306a36Sopenharmony_ci * Endpoint State - bits 0:2 72162306a36Sopenharmony_ci * 0 - disabled 72262306a36Sopenharmony_ci * 1 - running 72362306a36Sopenharmony_ci * 2 - halted due to halt condition - ok to manipulate endpoint ring 72462306a36Sopenharmony_ci * 3 - stopped 72562306a36Sopenharmony_ci * 4 - TRB error 72662306a36Sopenharmony_ci * 5-7 - reserved 72762306a36Sopenharmony_ci */ 72862306a36Sopenharmony_ci#define EP_STATE_MASK (0x7) 72962306a36Sopenharmony_ci#define EP_STATE_DISABLED 0 73062306a36Sopenharmony_ci#define EP_STATE_RUNNING 1 73162306a36Sopenharmony_ci#define EP_STATE_HALTED 2 73262306a36Sopenharmony_ci#define EP_STATE_STOPPED 3 73362306a36Sopenharmony_ci#define EP_STATE_ERROR 4 73462306a36Sopenharmony_ci#define GET_EP_CTX_STATE(ctx) (le32_to_cpu((ctx)->ep_info) & EP_STATE_MASK) 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci/* Mult - Max number of burtst within an interval, in EP companion desc. */ 73762306a36Sopenharmony_ci#define EP_MULT(p) (((p) & 0x3) << 8) 73862306a36Sopenharmony_ci#define CTX_TO_EP_MULT(p) (((p) >> 8) & 0x3) 73962306a36Sopenharmony_ci/* bits 10:14 are Max Primary Streams */ 74062306a36Sopenharmony_ci/* bit 15 is Linear Stream Array */ 74162306a36Sopenharmony_ci/* Interval - period between requests to an endpoint - 125u increments. */ 74262306a36Sopenharmony_ci#define EP_INTERVAL(p) (((p) & 0xff) << 16) 74362306a36Sopenharmony_ci#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) 74462306a36Sopenharmony_ci#define CTX_TO_EP_INTERVAL(p) (((p) >> 16) & 0xff) 74562306a36Sopenharmony_ci#define EP_MAXPSTREAMS_MASK (0x1f << 10) 74662306a36Sopenharmony_ci#define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) 74762306a36Sopenharmony_ci#define CTX_TO_EP_MAXPSTREAMS(p) (((p) & EP_MAXPSTREAMS_MASK) >> 10) 74862306a36Sopenharmony_ci/* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ 74962306a36Sopenharmony_ci#define EP_HAS_LSA (1 << 15) 75062306a36Sopenharmony_ci/* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ 75162306a36Sopenharmony_ci#define CTX_TO_MAX_ESIT_PAYLOAD_HI(p) (((p) >> 24) & 0xff) 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci/* ep_info2 bitmasks */ 75462306a36Sopenharmony_ci/* 75562306a36Sopenharmony_ci * Force Event - generate transfer events for all TRBs for this endpoint 75662306a36Sopenharmony_ci * This will tell the HC to ignore the IOC and ISP flags (for debugging only). 75762306a36Sopenharmony_ci */ 75862306a36Sopenharmony_ci#define FORCE_EVENT (0x1) 75962306a36Sopenharmony_ci#define ERROR_COUNT(p) (((p) & 0x3) << 1) 76062306a36Sopenharmony_ci#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) 76162306a36Sopenharmony_ci#define EP_TYPE(p) ((p) << 3) 76262306a36Sopenharmony_ci#define ISOC_OUT_EP 1 76362306a36Sopenharmony_ci#define BULK_OUT_EP 2 76462306a36Sopenharmony_ci#define INT_OUT_EP 3 76562306a36Sopenharmony_ci#define CTRL_EP 4 76662306a36Sopenharmony_ci#define ISOC_IN_EP 5 76762306a36Sopenharmony_ci#define BULK_IN_EP 6 76862306a36Sopenharmony_ci#define INT_IN_EP 7 76962306a36Sopenharmony_ci/* bit 6 reserved */ 77062306a36Sopenharmony_ci/* bit 7 is Host Initiate Disable - for disabling stream selection */ 77162306a36Sopenharmony_ci#define MAX_BURST(p) (((p)&0xff) << 8) 77262306a36Sopenharmony_ci#define CTX_TO_MAX_BURST(p) (((p) >> 8) & 0xff) 77362306a36Sopenharmony_ci#define MAX_PACKET(p) (((p)&0xffff) << 16) 77462306a36Sopenharmony_ci#define MAX_PACKET_MASK (0xffff << 16) 77562306a36Sopenharmony_ci#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci/* tx_info bitmasks */ 77862306a36Sopenharmony_ci#define EP_AVG_TRB_LENGTH(p) ((p) & 0xffff) 77962306a36Sopenharmony_ci#define EP_MAX_ESIT_PAYLOAD_LO(p) (((p) & 0xffff) << 16) 78062306a36Sopenharmony_ci#define EP_MAX_ESIT_PAYLOAD_HI(p) ((((p) >> 16) & 0xff) << 24) 78162306a36Sopenharmony_ci#define CTX_TO_MAX_ESIT_PAYLOAD(p) (((p) >> 16) & 0xffff) 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci/* deq bitmasks */ 78462306a36Sopenharmony_ci#define EP_CTX_CYCLE_MASK (1 << 0) 78562306a36Sopenharmony_ci#define SCTX_DEQ_MASK (~0xfL) 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci/** 78962306a36Sopenharmony_ci * struct xhci_input_control_context 79062306a36Sopenharmony_ci * Input control context; see section 6.2.5. 79162306a36Sopenharmony_ci * 79262306a36Sopenharmony_ci * @drop_context: set the bit of the endpoint context you want to disable 79362306a36Sopenharmony_ci * @add_context: set the bit of the endpoint context you want to enable 79462306a36Sopenharmony_ci */ 79562306a36Sopenharmony_cistruct xhci_input_control_ctx { 79662306a36Sopenharmony_ci __le32 drop_flags; 79762306a36Sopenharmony_ci __le32 add_flags; 79862306a36Sopenharmony_ci __le32 rsvd2[6]; 79962306a36Sopenharmony_ci}; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci#define EP_IS_ADDED(ctrl_ctx, i) \ 80262306a36Sopenharmony_ci (le32_to_cpu(ctrl_ctx->add_flags) & (1 << (i + 1))) 80362306a36Sopenharmony_ci#define EP_IS_DROPPED(ctrl_ctx, i) \ 80462306a36Sopenharmony_ci (le32_to_cpu(ctrl_ctx->drop_flags) & (1 << (i + 1))) 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci/* Represents everything that is needed to issue a command on the command ring. 80762306a36Sopenharmony_ci * It's useful to pre-allocate these for commands that cannot fail due to 80862306a36Sopenharmony_ci * out-of-memory errors, like freeing streams. 80962306a36Sopenharmony_ci */ 81062306a36Sopenharmony_cistruct xhci_command { 81162306a36Sopenharmony_ci /* Input context for changing device state */ 81262306a36Sopenharmony_ci struct xhci_container_ctx *in_ctx; 81362306a36Sopenharmony_ci u32 status; 81462306a36Sopenharmony_ci int slot_id; 81562306a36Sopenharmony_ci /* If completion is null, no one is waiting on this command 81662306a36Sopenharmony_ci * and the structure can be freed after the command completes. 81762306a36Sopenharmony_ci */ 81862306a36Sopenharmony_ci struct completion *completion; 81962306a36Sopenharmony_ci union xhci_trb *command_trb; 82062306a36Sopenharmony_ci struct list_head cmd_list; 82162306a36Sopenharmony_ci}; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci/* drop context bitmasks */ 82462306a36Sopenharmony_ci#define DROP_EP(x) (0x1 << x) 82562306a36Sopenharmony_ci/* add context bitmasks */ 82662306a36Sopenharmony_ci#define ADD_EP(x) (0x1 << x) 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_cistruct xhci_stream_ctx { 82962306a36Sopenharmony_ci /* 64-bit stream ring address, cycle state, and stream type */ 83062306a36Sopenharmony_ci __le64 stream_ring; 83162306a36Sopenharmony_ci /* offset 0x14 - 0x1f reserved for HC internal use */ 83262306a36Sopenharmony_ci __le32 reserved[2]; 83362306a36Sopenharmony_ci}; 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */ 83662306a36Sopenharmony_ci#define SCT_FOR_CTX(p) (((p) & 0x7) << 1) 83762306a36Sopenharmony_ci/* Secondary stream array type, dequeue pointer is to a transfer ring */ 83862306a36Sopenharmony_ci#define SCT_SEC_TR 0 83962306a36Sopenharmony_ci/* Primary stream array type, dequeue pointer is to a transfer ring */ 84062306a36Sopenharmony_ci#define SCT_PRI_TR 1 84162306a36Sopenharmony_ci/* Dequeue pointer is for a secondary stream array (SSA) with 8 entries */ 84262306a36Sopenharmony_ci#define SCT_SSA_8 2 84362306a36Sopenharmony_ci#define SCT_SSA_16 3 84462306a36Sopenharmony_ci#define SCT_SSA_32 4 84562306a36Sopenharmony_ci#define SCT_SSA_64 5 84662306a36Sopenharmony_ci#define SCT_SSA_128 6 84762306a36Sopenharmony_ci#define SCT_SSA_256 7 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci/* Assume no secondary streams for now */ 85062306a36Sopenharmony_cistruct xhci_stream_info { 85162306a36Sopenharmony_ci struct xhci_ring **stream_rings; 85262306a36Sopenharmony_ci /* Number of streams, including stream 0 (which drivers can't use) */ 85362306a36Sopenharmony_ci unsigned int num_streams; 85462306a36Sopenharmony_ci /* The stream context array may be bigger than 85562306a36Sopenharmony_ci * the number of streams the driver asked for 85662306a36Sopenharmony_ci */ 85762306a36Sopenharmony_ci struct xhci_stream_ctx *stream_ctx_array; 85862306a36Sopenharmony_ci unsigned int num_stream_ctxs; 85962306a36Sopenharmony_ci dma_addr_t ctx_array_dma; 86062306a36Sopenharmony_ci /* For mapping physical TRB addresses to segments in stream rings */ 86162306a36Sopenharmony_ci struct radix_tree_root trb_address_map; 86262306a36Sopenharmony_ci struct xhci_command *free_streams_command; 86362306a36Sopenharmony_ci}; 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci#define SMALL_STREAM_ARRAY_SIZE 256 86662306a36Sopenharmony_ci#define MEDIUM_STREAM_ARRAY_SIZE 1024 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci/* Some Intel xHCI host controllers need software to keep track of the bus 86962306a36Sopenharmony_ci * bandwidth. Keep track of endpoint info here. Each root port is allocated 87062306a36Sopenharmony_ci * the full bus bandwidth. We must also treat TTs (including each port under a 87162306a36Sopenharmony_ci * multi-TT hub) as a separate bandwidth domain. The direct memory interface 87262306a36Sopenharmony_ci * (DMI) also limits the total bandwidth (across all domains) that can be used. 87362306a36Sopenharmony_ci */ 87462306a36Sopenharmony_cistruct xhci_bw_info { 87562306a36Sopenharmony_ci /* ep_interval is zero-based */ 87662306a36Sopenharmony_ci unsigned int ep_interval; 87762306a36Sopenharmony_ci /* mult and num_packets are one-based */ 87862306a36Sopenharmony_ci unsigned int mult; 87962306a36Sopenharmony_ci unsigned int num_packets; 88062306a36Sopenharmony_ci unsigned int max_packet_size; 88162306a36Sopenharmony_ci unsigned int max_esit_payload; 88262306a36Sopenharmony_ci unsigned int type; 88362306a36Sopenharmony_ci}; 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci/* "Block" sizes in bytes the hardware uses for different device speeds. 88662306a36Sopenharmony_ci * The logic in this part of the hardware limits the number of bits the hardware 88762306a36Sopenharmony_ci * can use, so must represent bandwidth in a less precise manner to mimic what 88862306a36Sopenharmony_ci * the scheduler hardware computes. 88962306a36Sopenharmony_ci */ 89062306a36Sopenharmony_ci#define FS_BLOCK 1 89162306a36Sopenharmony_ci#define HS_BLOCK 4 89262306a36Sopenharmony_ci#define SS_BLOCK 16 89362306a36Sopenharmony_ci#define DMI_BLOCK 32 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci/* Each device speed has a protocol overhead (CRC, bit stuffing, etc) associated 89662306a36Sopenharmony_ci * with each byte transferred. SuperSpeed devices have an initial overhead to 89762306a36Sopenharmony_ci * set up bursts. These are in blocks, see above. LS overhead has already been 89862306a36Sopenharmony_ci * translated into FS blocks. 89962306a36Sopenharmony_ci */ 90062306a36Sopenharmony_ci#define DMI_OVERHEAD 8 90162306a36Sopenharmony_ci#define DMI_OVERHEAD_BURST 4 90262306a36Sopenharmony_ci#define SS_OVERHEAD 8 90362306a36Sopenharmony_ci#define SS_OVERHEAD_BURST 32 90462306a36Sopenharmony_ci#define HS_OVERHEAD 26 90562306a36Sopenharmony_ci#define FS_OVERHEAD 20 90662306a36Sopenharmony_ci#define LS_OVERHEAD 128 90762306a36Sopenharmony_ci/* The TTs need to claim roughly twice as much bandwidth (94 bytes per 90862306a36Sopenharmony_ci * microframe ~= 24Mbps) of the HS bus as the devices can actually use because 90962306a36Sopenharmony_ci * of overhead associated with split transfers crossing microframe boundaries. 91062306a36Sopenharmony_ci * 31 blocks is pure protocol overhead. 91162306a36Sopenharmony_ci */ 91262306a36Sopenharmony_ci#define TT_HS_OVERHEAD (31 + 94) 91362306a36Sopenharmony_ci#define TT_DMI_OVERHEAD (25 + 12) 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci/* Bandwidth limits in blocks */ 91662306a36Sopenharmony_ci#define FS_BW_LIMIT 1285 91762306a36Sopenharmony_ci#define TT_BW_LIMIT 1320 91862306a36Sopenharmony_ci#define HS_BW_LIMIT 1607 91962306a36Sopenharmony_ci#define SS_BW_LIMIT_IN 3906 92062306a36Sopenharmony_ci#define DMI_BW_LIMIT_IN 3906 92162306a36Sopenharmony_ci#define SS_BW_LIMIT_OUT 3906 92262306a36Sopenharmony_ci#define DMI_BW_LIMIT_OUT 3906 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci/* Percentage of bus bandwidth reserved for non-periodic transfers */ 92562306a36Sopenharmony_ci#define FS_BW_RESERVED 10 92662306a36Sopenharmony_ci#define HS_BW_RESERVED 20 92762306a36Sopenharmony_ci#define SS_BW_RESERVED 10 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_cistruct xhci_virt_ep { 93062306a36Sopenharmony_ci struct xhci_virt_device *vdev; /* parent */ 93162306a36Sopenharmony_ci unsigned int ep_index; 93262306a36Sopenharmony_ci struct xhci_ring *ring; 93362306a36Sopenharmony_ci /* Related to endpoints that are configured to use stream IDs only */ 93462306a36Sopenharmony_ci struct xhci_stream_info *stream_info; 93562306a36Sopenharmony_ci /* Temporary storage in case the configure endpoint command fails and we 93662306a36Sopenharmony_ci * have to restore the device state to the previous state 93762306a36Sopenharmony_ci */ 93862306a36Sopenharmony_ci struct xhci_ring *new_ring; 93962306a36Sopenharmony_ci unsigned int err_count; 94062306a36Sopenharmony_ci unsigned int ep_state; 94162306a36Sopenharmony_ci#define SET_DEQ_PENDING (1 << 0) 94262306a36Sopenharmony_ci#define EP_HALTED (1 << 1) /* For stall handling */ 94362306a36Sopenharmony_ci#define EP_STOP_CMD_PENDING (1 << 2) /* For URB cancellation */ 94462306a36Sopenharmony_ci/* Transitioning the endpoint to using streams, don't enqueue URBs */ 94562306a36Sopenharmony_ci#define EP_GETTING_STREAMS (1 << 3) 94662306a36Sopenharmony_ci#define EP_HAS_STREAMS (1 << 4) 94762306a36Sopenharmony_ci/* Transitioning the endpoint to not using streams, don't enqueue URBs */ 94862306a36Sopenharmony_ci#define EP_GETTING_NO_STREAMS (1 << 5) 94962306a36Sopenharmony_ci#define EP_HARD_CLEAR_TOGGLE (1 << 6) 95062306a36Sopenharmony_ci#define EP_SOFT_CLEAR_TOGGLE (1 << 7) 95162306a36Sopenharmony_ci/* usb_hub_clear_tt_buffer is in progress */ 95262306a36Sopenharmony_ci#define EP_CLEARING_TT (1 << 8) 95362306a36Sopenharmony_ci /* ---- Related to URB cancellation ---- */ 95462306a36Sopenharmony_ci struct list_head cancelled_td_list; 95562306a36Sopenharmony_ci struct xhci_hcd *xhci; 95662306a36Sopenharmony_ci /* Dequeue pointer and dequeue segment for a submitted Set TR Dequeue 95762306a36Sopenharmony_ci * command. We'll need to update the ring's dequeue segment and dequeue 95862306a36Sopenharmony_ci * pointer after the command completes. 95962306a36Sopenharmony_ci */ 96062306a36Sopenharmony_ci struct xhci_segment *queued_deq_seg; 96162306a36Sopenharmony_ci union xhci_trb *queued_deq_ptr; 96262306a36Sopenharmony_ci /* 96362306a36Sopenharmony_ci * Sometimes the xHC can not process isochronous endpoint ring quickly 96462306a36Sopenharmony_ci * enough, and it will miss some isoc tds on the ring and generate 96562306a36Sopenharmony_ci * a Missed Service Error Event. 96662306a36Sopenharmony_ci * Set skip flag when receive a Missed Service Error Event and 96762306a36Sopenharmony_ci * process the missed tds on the endpoint ring. 96862306a36Sopenharmony_ci */ 96962306a36Sopenharmony_ci bool skip; 97062306a36Sopenharmony_ci /* Bandwidth checking storage */ 97162306a36Sopenharmony_ci struct xhci_bw_info bw_info; 97262306a36Sopenharmony_ci struct list_head bw_endpoint_list; 97362306a36Sopenharmony_ci /* Isoch Frame ID checking storage */ 97462306a36Sopenharmony_ci int next_frame_id; 97562306a36Sopenharmony_ci /* Use new Isoch TRB layout needed for extended TBC support */ 97662306a36Sopenharmony_ci bool use_extended_tbc; 97762306a36Sopenharmony_ci}; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_cienum xhci_overhead_type { 98062306a36Sopenharmony_ci LS_OVERHEAD_TYPE = 0, 98162306a36Sopenharmony_ci FS_OVERHEAD_TYPE, 98262306a36Sopenharmony_ci HS_OVERHEAD_TYPE, 98362306a36Sopenharmony_ci}; 98462306a36Sopenharmony_ci 98562306a36Sopenharmony_cistruct xhci_interval_bw { 98662306a36Sopenharmony_ci unsigned int num_packets; 98762306a36Sopenharmony_ci /* Sorted by max packet size. 98862306a36Sopenharmony_ci * Head of the list is the greatest max packet size. 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_ci struct list_head endpoints; 99162306a36Sopenharmony_ci /* How many endpoints of each speed are present. */ 99262306a36Sopenharmony_ci unsigned int overhead[3]; 99362306a36Sopenharmony_ci}; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci#define XHCI_MAX_INTERVAL 16 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_cistruct xhci_interval_bw_table { 99862306a36Sopenharmony_ci unsigned int interval0_esit_payload; 99962306a36Sopenharmony_ci struct xhci_interval_bw interval_bw[XHCI_MAX_INTERVAL]; 100062306a36Sopenharmony_ci /* Includes reserved bandwidth for async endpoints */ 100162306a36Sopenharmony_ci unsigned int bw_used; 100262306a36Sopenharmony_ci unsigned int ss_bw_in; 100362306a36Sopenharmony_ci unsigned int ss_bw_out; 100462306a36Sopenharmony_ci}; 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_ci#define EP_CTX_PER_DEV 31 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_cistruct xhci_virt_device { 100962306a36Sopenharmony_ci int slot_id; 101062306a36Sopenharmony_ci struct usb_device *udev; 101162306a36Sopenharmony_ci /* 101262306a36Sopenharmony_ci * Commands to the hardware are passed an "input context" that 101362306a36Sopenharmony_ci * tells the hardware what to change in its data structures. 101462306a36Sopenharmony_ci * The hardware will return changes in an "output context" that 101562306a36Sopenharmony_ci * software must allocate for the hardware. We need to keep 101662306a36Sopenharmony_ci * track of input and output contexts separately because 101762306a36Sopenharmony_ci * these commands might fail and we don't trust the hardware. 101862306a36Sopenharmony_ci */ 101962306a36Sopenharmony_ci struct xhci_container_ctx *out_ctx; 102062306a36Sopenharmony_ci /* Used for addressing devices and configuration changes */ 102162306a36Sopenharmony_ci struct xhci_container_ctx *in_ctx; 102262306a36Sopenharmony_ci struct xhci_virt_ep eps[EP_CTX_PER_DEV]; 102362306a36Sopenharmony_ci u8 fake_port; 102462306a36Sopenharmony_ci u8 real_port; 102562306a36Sopenharmony_ci struct xhci_interval_bw_table *bw_table; 102662306a36Sopenharmony_ci struct xhci_tt_bw_info *tt_info; 102762306a36Sopenharmony_ci /* 102862306a36Sopenharmony_ci * flags for state tracking based on events and issued commands. 102962306a36Sopenharmony_ci * Software can not rely on states from output contexts because of 103062306a36Sopenharmony_ci * latency between events and xHC updating output context values. 103162306a36Sopenharmony_ci * See xhci 1.1 section 4.8.3 for more details 103262306a36Sopenharmony_ci */ 103362306a36Sopenharmony_ci unsigned long flags; 103462306a36Sopenharmony_ci#define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */ 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci /* The current max exit latency for the enabled USB3 link states. */ 103762306a36Sopenharmony_ci u16 current_mel; 103862306a36Sopenharmony_ci /* Used for the debugfs interfaces. */ 103962306a36Sopenharmony_ci void *debugfs_private; 104062306a36Sopenharmony_ci}; 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci/* 104362306a36Sopenharmony_ci * For each roothub, keep track of the bandwidth information for each periodic 104462306a36Sopenharmony_ci * interval. 104562306a36Sopenharmony_ci * 104662306a36Sopenharmony_ci * If a high speed hub is attached to the roothub, each TT associated with that 104762306a36Sopenharmony_ci * hub is a separate bandwidth domain. The interval information for the 104862306a36Sopenharmony_ci * endpoints on the devices under that TT will appear in the TT structure. 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_cistruct xhci_root_port_bw_info { 105162306a36Sopenharmony_ci struct list_head tts; 105262306a36Sopenharmony_ci unsigned int num_active_tts; 105362306a36Sopenharmony_ci struct xhci_interval_bw_table bw_table; 105462306a36Sopenharmony_ci}; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistruct xhci_tt_bw_info { 105762306a36Sopenharmony_ci struct list_head tt_list; 105862306a36Sopenharmony_ci int slot_id; 105962306a36Sopenharmony_ci int ttport; 106062306a36Sopenharmony_ci struct xhci_interval_bw_table bw_table; 106162306a36Sopenharmony_ci int active_eps; 106262306a36Sopenharmony_ci}; 106362306a36Sopenharmony_ci 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_ci/** 106662306a36Sopenharmony_ci * struct xhci_device_context_array 106762306a36Sopenharmony_ci * @dev_context_ptr array of 64-bit DMA addresses for device contexts 106862306a36Sopenharmony_ci */ 106962306a36Sopenharmony_cistruct xhci_device_context_array { 107062306a36Sopenharmony_ci /* 64-bit device addresses; we only write 32-bit addresses */ 107162306a36Sopenharmony_ci __le64 dev_context_ptrs[MAX_HC_SLOTS]; 107262306a36Sopenharmony_ci /* private xHCD pointers */ 107362306a36Sopenharmony_ci dma_addr_t dma; 107462306a36Sopenharmony_ci}; 107562306a36Sopenharmony_ci/* TODO: write function to set the 64-bit device DMA address */ 107662306a36Sopenharmony_ci/* 107762306a36Sopenharmony_ci * TODO: change this to be dynamically sized at HC mem init time since the HC 107862306a36Sopenharmony_ci * might not be able to handle the maximum number of devices possible. 107962306a36Sopenharmony_ci */ 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_cistruct xhci_transfer_event { 108362306a36Sopenharmony_ci /* 64-bit buffer address, or immediate data */ 108462306a36Sopenharmony_ci __le64 buffer; 108562306a36Sopenharmony_ci __le32 transfer_len; 108662306a36Sopenharmony_ci /* This field is interpreted differently based on the type of TRB */ 108762306a36Sopenharmony_ci __le32 flags; 108862306a36Sopenharmony_ci}; 108962306a36Sopenharmony_ci 109062306a36Sopenharmony_ci/* Transfer event TRB length bit mask */ 109162306a36Sopenharmony_ci/* bits 0:23 */ 109262306a36Sopenharmony_ci#define EVENT_TRB_LEN(p) ((p) & 0xffffff) 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci/** Transfer Event bit fields **/ 109562306a36Sopenharmony_ci#define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_ci/* Completion Code - only applicable for some types of TRBs */ 109862306a36Sopenharmony_ci#define COMP_CODE_MASK (0xff << 24) 109962306a36Sopenharmony_ci#define GET_COMP_CODE(p) (((p) & COMP_CODE_MASK) >> 24) 110062306a36Sopenharmony_ci#define COMP_INVALID 0 110162306a36Sopenharmony_ci#define COMP_SUCCESS 1 110262306a36Sopenharmony_ci#define COMP_DATA_BUFFER_ERROR 2 110362306a36Sopenharmony_ci#define COMP_BABBLE_DETECTED_ERROR 3 110462306a36Sopenharmony_ci#define COMP_USB_TRANSACTION_ERROR 4 110562306a36Sopenharmony_ci#define COMP_TRB_ERROR 5 110662306a36Sopenharmony_ci#define COMP_STALL_ERROR 6 110762306a36Sopenharmony_ci#define COMP_RESOURCE_ERROR 7 110862306a36Sopenharmony_ci#define COMP_BANDWIDTH_ERROR 8 110962306a36Sopenharmony_ci#define COMP_NO_SLOTS_AVAILABLE_ERROR 9 111062306a36Sopenharmony_ci#define COMP_INVALID_STREAM_TYPE_ERROR 10 111162306a36Sopenharmony_ci#define COMP_SLOT_NOT_ENABLED_ERROR 11 111262306a36Sopenharmony_ci#define COMP_ENDPOINT_NOT_ENABLED_ERROR 12 111362306a36Sopenharmony_ci#define COMP_SHORT_PACKET 13 111462306a36Sopenharmony_ci#define COMP_RING_UNDERRUN 14 111562306a36Sopenharmony_ci#define COMP_RING_OVERRUN 15 111662306a36Sopenharmony_ci#define COMP_VF_EVENT_RING_FULL_ERROR 16 111762306a36Sopenharmony_ci#define COMP_PARAMETER_ERROR 17 111862306a36Sopenharmony_ci#define COMP_BANDWIDTH_OVERRUN_ERROR 18 111962306a36Sopenharmony_ci#define COMP_CONTEXT_STATE_ERROR 19 112062306a36Sopenharmony_ci#define COMP_NO_PING_RESPONSE_ERROR 20 112162306a36Sopenharmony_ci#define COMP_EVENT_RING_FULL_ERROR 21 112262306a36Sopenharmony_ci#define COMP_INCOMPATIBLE_DEVICE_ERROR 22 112362306a36Sopenharmony_ci#define COMP_MISSED_SERVICE_ERROR 23 112462306a36Sopenharmony_ci#define COMP_COMMAND_RING_STOPPED 24 112562306a36Sopenharmony_ci#define COMP_COMMAND_ABORTED 25 112662306a36Sopenharmony_ci#define COMP_STOPPED 26 112762306a36Sopenharmony_ci#define COMP_STOPPED_LENGTH_INVALID 27 112862306a36Sopenharmony_ci#define COMP_STOPPED_SHORT_PACKET 28 112962306a36Sopenharmony_ci#define COMP_MAX_EXIT_LATENCY_TOO_LARGE_ERROR 29 113062306a36Sopenharmony_ci#define COMP_ISOCH_BUFFER_OVERRUN 31 113162306a36Sopenharmony_ci#define COMP_EVENT_LOST_ERROR 32 113262306a36Sopenharmony_ci#define COMP_UNDEFINED_ERROR 33 113362306a36Sopenharmony_ci#define COMP_INVALID_STREAM_ID_ERROR 34 113462306a36Sopenharmony_ci#define COMP_SECONDARY_BANDWIDTH_ERROR 35 113562306a36Sopenharmony_ci#define COMP_SPLIT_TRANSACTION_ERROR 36 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_cistatic inline const char *xhci_trb_comp_code_string(u8 status) 113862306a36Sopenharmony_ci{ 113962306a36Sopenharmony_ci switch (status) { 114062306a36Sopenharmony_ci case COMP_INVALID: 114162306a36Sopenharmony_ci return "Invalid"; 114262306a36Sopenharmony_ci case COMP_SUCCESS: 114362306a36Sopenharmony_ci return "Success"; 114462306a36Sopenharmony_ci case COMP_DATA_BUFFER_ERROR: 114562306a36Sopenharmony_ci return "Data Buffer Error"; 114662306a36Sopenharmony_ci case COMP_BABBLE_DETECTED_ERROR: 114762306a36Sopenharmony_ci return "Babble Detected"; 114862306a36Sopenharmony_ci case COMP_USB_TRANSACTION_ERROR: 114962306a36Sopenharmony_ci return "USB Transaction Error"; 115062306a36Sopenharmony_ci case COMP_TRB_ERROR: 115162306a36Sopenharmony_ci return "TRB Error"; 115262306a36Sopenharmony_ci case COMP_STALL_ERROR: 115362306a36Sopenharmony_ci return "Stall Error"; 115462306a36Sopenharmony_ci case COMP_RESOURCE_ERROR: 115562306a36Sopenharmony_ci return "Resource Error"; 115662306a36Sopenharmony_ci case COMP_BANDWIDTH_ERROR: 115762306a36Sopenharmony_ci return "Bandwidth Error"; 115862306a36Sopenharmony_ci case COMP_NO_SLOTS_AVAILABLE_ERROR: 115962306a36Sopenharmony_ci return "No Slots Available Error"; 116062306a36Sopenharmony_ci case COMP_INVALID_STREAM_TYPE_ERROR: 116162306a36Sopenharmony_ci return "Invalid Stream Type Error"; 116262306a36Sopenharmony_ci case COMP_SLOT_NOT_ENABLED_ERROR: 116362306a36Sopenharmony_ci return "Slot Not Enabled Error"; 116462306a36Sopenharmony_ci case COMP_ENDPOINT_NOT_ENABLED_ERROR: 116562306a36Sopenharmony_ci return "Endpoint Not Enabled Error"; 116662306a36Sopenharmony_ci case COMP_SHORT_PACKET: 116762306a36Sopenharmony_ci return "Short Packet"; 116862306a36Sopenharmony_ci case COMP_RING_UNDERRUN: 116962306a36Sopenharmony_ci return "Ring Underrun"; 117062306a36Sopenharmony_ci case COMP_RING_OVERRUN: 117162306a36Sopenharmony_ci return "Ring Overrun"; 117262306a36Sopenharmony_ci case COMP_VF_EVENT_RING_FULL_ERROR: 117362306a36Sopenharmony_ci return "VF Event Ring Full Error"; 117462306a36Sopenharmony_ci case COMP_PARAMETER_ERROR: 117562306a36Sopenharmony_ci return "Parameter Error"; 117662306a36Sopenharmony_ci case COMP_BANDWIDTH_OVERRUN_ERROR: 117762306a36Sopenharmony_ci return "Bandwidth Overrun Error"; 117862306a36Sopenharmony_ci case COMP_CONTEXT_STATE_ERROR: 117962306a36Sopenharmony_ci return "Context State Error"; 118062306a36Sopenharmony_ci case COMP_NO_PING_RESPONSE_ERROR: 118162306a36Sopenharmony_ci return "No Ping Response Error"; 118262306a36Sopenharmony_ci case COMP_EVENT_RING_FULL_ERROR: 118362306a36Sopenharmony_ci return "Event Ring Full Error"; 118462306a36Sopenharmony_ci case COMP_INCOMPATIBLE_DEVICE_ERROR: 118562306a36Sopenharmony_ci return "Incompatible Device Error"; 118662306a36Sopenharmony_ci case COMP_MISSED_SERVICE_ERROR: 118762306a36Sopenharmony_ci return "Missed Service Error"; 118862306a36Sopenharmony_ci case COMP_COMMAND_RING_STOPPED: 118962306a36Sopenharmony_ci return "Command Ring Stopped"; 119062306a36Sopenharmony_ci case COMP_COMMAND_ABORTED: 119162306a36Sopenharmony_ci return "Command Aborted"; 119262306a36Sopenharmony_ci case COMP_STOPPED: 119362306a36Sopenharmony_ci return "Stopped"; 119462306a36Sopenharmony_ci case COMP_STOPPED_LENGTH_INVALID: 119562306a36Sopenharmony_ci return "Stopped - Length Invalid"; 119662306a36Sopenharmony_ci case COMP_STOPPED_SHORT_PACKET: 119762306a36Sopenharmony_ci return "Stopped - Short Packet"; 119862306a36Sopenharmony_ci case COMP_MAX_EXIT_LATENCY_TOO_LARGE_ERROR: 119962306a36Sopenharmony_ci return "Max Exit Latency Too Large Error"; 120062306a36Sopenharmony_ci case COMP_ISOCH_BUFFER_OVERRUN: 120162306a36Sopenharmony_ci return "Isoch Buffer Overrun"; 120262306a36Sopenharmony_ci case COMP_EVENT_LOST_ERROR: 120362306a36Sopenharmony_ci return "Event Lost Error"; 120462306a36Sopenharmony_ci case COMP_UNDEFINED_ERROR: 120562306a36Sopenharmony_ci return "Undefined Error"; 120662306a36Sopenharmony_ci case COMP_INVALID_STREAM_ID_ERROR: 120762306a36Sopenharmony_ci return "Invalid Stream ID Error"; 120862306a36Sopenharmony_ci case COMP_SECONDARY_BANDWIDTH_ERROR: 120962306a36Sopenharmony_ci return "Secondary Bandwidth Error"; 121062306a36Sopenharmony_ci case COMP_SPLIT_TRANSACTION_ERROR: 121162306a36Sopenharmony_ci return "Split Transaction Error"; 121262306a36Sopenharmony_ci default: 121362306a36Sopenharmony_ci return "Unknown!!"; 121462306a36Sopenharmony_ci } 121562306a36Sopenharmony_ci} 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistruct xhci_link_trb { 121862306a36Sopenharmony_ci /* 64-bit segment pointer*/ 121962306a36Sopenharmony_ci __le64 segment_ptr; 122062306a36Sopenharmony_ci __le32 intr_target; 122162306a36Sopenharmony_ci __le32 control; 122262306a36Sopenharmony_ci}; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci/* control bitfields */ 122562306a36Sopenharmony_ci#define LINK_TOGGLE (0x1<<1) 122662306a36Sopenharmony_ci 122762306a36Sopenharmony_ci/* Command completion event TRB */ 122862306a36Sopenharmony_cistruct xhci_event_cmd { 122962306a36Sopenharmony_ci /* Pointer to command TRB, or the value passed by the event data trb */ 123062306a36Sopenharmony_ci __le64 cmd_trb; 123162306a36Sopenharmony_ci __le32 status; 123262306a36Sopenharmony_ci __le32 flags; 123362306a36Sopenharmony_ci}; 123462306a36Sopenharmony_ci 123562306a36Sopenharmony_ci/* flags bitmasks */ 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_ci/* Address device - disable SetAddress */ 123862306a36Sopenharmony_ci#define TRB_BSR (1<<9) 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_ci/* Configure Endpoint - Deconfigure */ 124162306a36Sopenharmony_ci#define TRB_DC (1<<9) 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ci/* Stop Ring - Transfer State Preserve */ 124462306a36Sopenharmony_ci#define TRB_TSP (1<<9) 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_cienum xhci_ep_reset_type { 124762306a36Sopenharmony_ci EP_HARD_RESET, 124862306a36Sopenharmony_ci EP_SOFT_RESET, 124962306a36Sopenharmony_ci}; 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci/* Force Event */ 125262306a36Sopenharmony_ci#define TRB_TO_VF_INTR_TARGET(p) (((p) & (0x3ff << 22)) >> 22) 125362306a36Sopenharmony_ci#define TRB_TO_VF_ID(p) (((p) & (0xff << 16)) >> 16) 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci/* Set Latency Tolerance Value */ 125662306a36Sopenharmony_ci#define TRB_TO_BELT(p) (((p) & (0xfff << 16)) >> 16) 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci/* Get Port Bandwidth */ 125962306a36Sopenharmony_ci#define TRB_TO_DEV_SPEED(p) (((p) & (0xf << 16)) >> 16) 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_ci/* Force Header */ 126262306a36Sopenharmony_ci#define TRB_TO_PACKET_TYPE(p) ((p) & 0x1f) 126362306a36Sopenharmony_ci#define TRB_TO_ROOTHUB_PORT(p) (((p) & (0xff << 24)) >> 24) 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_cienum xhci_setup_dev { 126662306a36Sopenharmony_ci SETUP_CONTEXT_ONLY, 126762306a36Sopenharmony_ci SETUP_CONTEXT_ADDRESS, 126862306a36Sopenharmony_ci}; 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci/* bits 16:23 are the virtual function ID */ 127162306a36Sopenharmony_ci/* bits 24:31 are the slot ID */ 127262306a36Sopenharmony_ci#define TRB_TO_SLOT_ID(p) (((p) & (0xff<<24)) >> 24) 127362306a36Sopenharmony_ci#define SLOT_ID_FOR_TRB(p) (((p) & 0xff) << 24) 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci/* Stop Endpoint TRB - ep_index to endpoint ID for this TRB */ 127662306a36Sopenharmony_ci#define TRB_TO_EP_INDEX(p) ((((p) & (0x1f << 16)) >> 16) - 1) 127762306a36Sopenharmony_ci#define EP_ID_FOR_TRB(p) ((((p) + 1) & 0x1f) << 16) 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci#define SUSPEND_PORT_FOR_TRB(p) (((p) & 1) << 23) 128062306a36Sopenharmony_ci#define TRB_TO_SUSPEND_PORT(p) (((p) & (1 << 23)) >> 23) 128162306a36Sopenharmony_ci#define LAST_EP_INDEX 30 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci/* Set TR Dequeue Pointer command TRB fields, 6.4.3.9 */ 128462306a36Sopenharmony_ci#define TRB_TO_STREAM_ID(p) ((((p) & (0xffff << 16)) >> 16)) 128562306a36Sopenharmony_ci#define STREAM_ID_FOR_TRB(p) ((((p)) & 0xffff) << 16) 128662306a36Sopenharmony_ci#define SCT_FOR_TRB(p) (((p) << 1) & 0x7) 128762306a36Sopenharmony_ci 128862306a36Sopenharmony_ci/* Link TRB specific fields */ 128962306a36Sopenharmony_ci#define TRB_TC (1<<1) 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci/* Port Status Change Event TRB fields */ 129262306a36Sopenharmony_ci/* Port ID - bits 31:24 */ 129362306a36Sopenharmony_ci#define GET_PORT_ID(p) (((p) & (0xff << 24)) >> 24) 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci#define EVENT_DATA (1 << 2) 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_ci/* Normal TRB fields */ 129862306a36Sopenharmony_ci/* transfer_len bitmasks - bits 0:16 */ 129962306a36Sopenharmony_ci#define TRB_LEN(p) ((p) & 0x1ffff) 130062306a36Sopenharmony_ci/* TD Size, packets remaining in this TD, bits 21:17 (5 bits, so max 31) */ 130162306a36Sopenharmony_ci#define TRB_TD_SIZE(p) (min((p), (u32)31) << 17) 130262306a36Sopenharmony_ci#define GET_TD_SIZE(p) (((p) & 0x3e0000) >> 17) 130362306a36Sopenharmony_ci/* xhci 1.1 uses the TD_SIZE field for TBC if Extended TBC is enabled (ETE) */ 130462306a36Sopenharmony_ci#define TRB_TD_SIZE_TBC(p) (min((p), (u32)31) << 17) 130562306a36Sopenharmony_ci/* Interrupter Target - which MSI-X vector to target the completion event at */ 130662306a36Sopenharmony_ci#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22) 130762306a36Sopenharmony_ci#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff) 130862306a36Sopenharmony_ci/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */ 130962306a36Sopenharmony_ci#define TRB_TBC(p) (((p) & 0x3) << 7) 131062306a36Sopenharmony_ci#define TRB_TLBPC(p) (((p) & 0xf) << 16) 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ci/* Cycle bit - indicates TRB ownership by HC or HCD */ 131362306a36Sopenharmony_ci#define TRB_CYCLE (1<<0) 131462306a36Sopenharmony_ci/* 131562306a36Sopenharmony_ci * Force next event data TRB to be evaluated before task switch. 131662306a36Sopenharmony_ci * Used to pass OS data back after a TD completes. 131762306a36Sopenharmony_ci */ 131862306a36Sopenharmony_ci#define TRB_ENT (1<<1) 131962306a36Sopenharmony_ci/* Interrupt on short packet */ 132062306a36Sopenharmony_ci#define TRB_ISP (1<<2) 132162306a36Sopenharmony_ci/* Set PCIe no snoop attribute */ 132262306a36Sopenharmony_ci#define TRB_NO_SNOOP (1<<3) 132362306a36Sopenharmony_ci/* Chain multiple TRBs into a TD */ 132462306a36Sopenharmony_ci#define TRB_CHAIN (1<<4) 132562306a36Sopenharmony_ci/* Interrupt on completion */ 132662306a36Sopenharmony_ci#define TRB_IOC (1<<5) 132762306a36Sopenharmony_ci/* The buffer pointer contains immediate data */ 132862306a36Sopenharmony_ci#define TRB_IDT (1<<6) 132962306a36Sopenharmony_ci/* TDs smaller than this might use IDT */ 133062306a36Sopenharmony_ci#define TRB_IDT_MAX_SIZE 8 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci/* Block Event Interrupt */ 133362306a36Sopenharmony_ci#define TRB_BEI (1<<9) 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci/* Control transfer TRB specific fields */ 133662306a36Sopenharmony_ci#define TRB_DIR_IN (1<<16) 133762306a36Sopenharmony_ci#define TRB_TX_TYPE(p) ((p) << 16) 133862306a36Sopenharmony_ci#define TRB_DATA_OUT 2 133962306a36Sopenharmony_ci#define TRB_DATA_IN 3 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci/* Isochronous TRB specific fields */ 134262306a36Sopenharmony_ci#define TRB_SIA (1<<31) 134362306a36Sopenharmony_ci#define TRB_FRAME_ID(p) (((p) & 0x7ff) << 20) 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci/* TRB cache size for xHC with TRB cache */ 134662306a36Sopenharmony_ci#define TRB_CACHE_SIZE_HS 8 134762306a36Sopenharmony_ci#define TRB_CACHE_SIZE_SS 16 134862306a36Sopenharmony_ci 134962306a36Sopenharmony_cistruct xhci_generic_trb { 135062306a36Sopenharmony_ci __le32 field[4]; 135162306a36Sopenharmony_ci}; 135262306a36Sopenharmony_ci 135362306a36Sopenharmony_ciunion xhci_trb { 135462306a36Sopenharmony_ci struct xhci_link_trb link; 135562306a36Sopenharmony_ci struct xhci_transfer_event trans_event; 135662306a36Sopenharmony_ci struct xhci_event_cmd event_cmd; 135762306a36Sopenharmony_ci struct xhci_generic_trb generic; 135862306a36Sopenharmony_ci}; 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci/* TRB bit mask */ 136162306a36Sopenharmony_ci#define TRB_TYPE_BITMASK (0xfc00) 136262306a36Sopenharmony_ci#define TRB_TYPE(p) ((p) << 10) 136362306a36Sopenharmony_ci#define TRB_FIELD_TO_TYPE(p) (((p) & TRB_TYPE_BITMASK) >> 10) 136462306a36Sopenharmony_ci/* TRB type IDs */ 136562306a36Sopenharmony_ci/* bulk, interrupt, isoc scatter/gather, and control data stage */ 136662306a36Sopenharmony_ci#define TRB_NORMAL 1 136762306a36Sopenharmony_ci/* setup stage for control transfers */ 136862306a36Sopenharmony_ci#define TRB_SETUP 2 136962306a36Sopenharmony_ci/* data stage for control transfers */ 137062306a36Sopenharmony_ci#define TRB_DATA 3 137162306a36Sopenharmony_ci/* status stage for control transfers */ 137262306a36Sopenharmony_ci#define TRB_STATUS 4 137362306a36Sopenharmony_ci/* isoc transfers */ 137462306a36Sopenharmony_ci#define TRB_ISOC 5 137562306a36Sopenharmony_ci/* TRB for linking ring segments */ 137662306a36Sopenharmony_ci#define TRB_LINK 6 137762306a36Sopenharmony_ci#define TRB_EVENT_DATA 7 137862306a36Sopenharmony_ci/* Transfer Ring No-op (not for the command ring) */ 137962306a36Sopenharmony_ci#define TRB_TR_NOOP 8 138062306a36Sopenharmony_ci/* Command TRBs */ 138162306a36Sopenharmony_ci/* Enable Slot Command */ 138262306a36Sopenharmony_ci#define TRB_ENABLE_SLOT 9 138362306a36Sopenharmony_ci/* Disable Slot Command */ 138462306a36Sopenharmony_ci#define TRB_DISABLE_SLOT 10 138562306a36Sopenharmony_ci/* Address Device Command */ 138662306a36Sopenharmony_ci#define TRB_ADDR_DEV 11 138762306a36Sopenharmony_ci/* Configure Endpoint Command */ 138862306a36Sopenharmony_ci#define TRB_CONFIG_EP 12 138962306a36Sopenharmony_ci/* Evaluate Context Command */ 139062306a36Sopenharmony_ci#define TRB_EVAL_CONTEXT 13 139162306a36Sopenharmony_ci/* Reset Endpoint Command */ 139262306a36Sopenharmony_ci#define TRB_RESET_EP 14 139362306a36Sopenharmony_ci/* Stop Transfer Ring Command */ 139462306a36Sopenharmony_ci#define TRB_STOP_RING 15 139562306a36Sopenharmony_ci/* Set Transfer Ring Dequeue Pointer Command */ 139662306a36Sopenharmony_ci#define TRB_SET_DEQ 16 139762306a36Sopenharmony_ci/* Reset Device Command */ 139862306a36Sopenharmony_ci#define TRB_RESET_DEV 17 139962306a36Sopenharmony_ci/* Force Event Command (opt) */ 140062306a36Sopenharmony_ci#define TRB_FORCE_EVENT 18 140162306a36Sopenharmony_ci/* Negotiate Bandwidth Command (opt) */ 140262306a36Sopenharmony_ci#define TRB_NEG_BANDWIDTH 19 140362306a36Sopenharmony_ci/* Set Latency Tolerance Value Command (opt) */ 140462306a36Sopenharmony_ci#define TRB_SET_LT 20 140562306a36Sopenharmony_ci/* Get port bandwidth Command */ 140662306a36Sopenharmony_ci#define TRB_GET_BW 21 140762306a36Sopenharmony_ci/* Force Header Command - generate a transaction or link management packet */ 140862306a36Sopenharmony_ci#define TRB_FORCE_HEADER 22 140962306a36Sopenharmony_ci/* No-op Command - not for transfer rings */ 141062306a36Sopenharmony_ci#define TRB_CMD_NOOP 23 141162306a36Sopenharmony_ci/* TRB IDs 24-31 reserved */ 141262306a36Sopenharmony_ci/* Event TRBS */ 141362306a36Sopenharmony_ci/* Transfer Event */ 141462306a36Sopenharmony_ci#define TRB_TRANSFER 32 141562306a36Sopenharmony_ci/* Command Completion Event */ 141662306a36Sopenharmony_ci#define TRB_COMPLETION 33 141762306a36Sopenharmony_ci/* Port Status Change Event */ 141862306a36Sopenharmony_ci#define TRB_PORT_STATUS 34 141962306a36Sopenharmony_ci/* Bandwidth Request Event (opt) */ 142062306a36Sopenharmony_ci#define TRB_BANDWIDTH_EVENT 35 142162306a36Sopenharmony_ci/* Doorbell Event (opt) */ 142262306a36Sopenharmony_ci#define TRB_DOORBELL 36 142362306a36Sopenharmony_ci/* Host Controller Event */ 142462306a36Sopenharmony_ci#define TRB_HC_EVENT 37 142562306a36Sopenharmony_ci/* Device Notification Event - device sent function wake notification */ 142662306a36Sopenharmony_ci#define TRB_DEV_NOTE 38 142762306a36Sopenharmony_ci/* MFINDEX Wrap Event - microframe counter wrapped */ 142862306a36Sopenharmony_ci#define TRB_MFINDEX_WRAP 39 142962306a36Sopenharmony_ci/* TRB IDs 40-47 reserved, 48-63 is vendor-defined */ 143062306a36Sopenharmony_ci#define TRB_VENDOR_DEFINED_LOW 48 143162306a36Sopenharmony_ci/* Nec vendor-specific command completion event. */ 143262306a36Sopenharmony_ci#define TRB_NEC_CMD_COMP 48 143362306a36Sopenharmony_ci/* Get NEC firmware revision. */ 143462306a36Sopenharmony_ci#define TRB_NEC_GET_FW 49 143562306a36Sopenharmony_ci 143662306a36Sopenharmony_cistatic inline const char *xhci_trb_type_string(u8 type) 143762306a36Sopenharmony_ci{ 143862306a36Sopenharmony_ci switch (type) { 143962306a36Sopenharmony_ci case TRB_NORMAL: 144062306a36Sopenharmony_ci return "Normal"; 144162306a36Sopenharmony_ci case TRB_SETUP: 144262306a36Sopenharmony_ci return "Setup Stage"; 144362306a36Sopenharmony_ci case TRB_DATA: 144462306a36Sopenharmony_ci return "Data Stage"; 144562306a36Sopenharmony_ci case TRB_STATUS: 144662306a36Sopenharmony_ci return "Status Stage"; 144762306a36Sopenharmony_ci case TRB_ISOC: 144862306a36Sopenharmony_ci return "Isoch"; 144962306a36Sopenharmony_ci case TRB_LINK: 145062306a36Sopenharmony_ci return "Link"; 145162306a36Sopenharmony_ci case TRB_EVENT_DATA: 145262306a36Sopenharmony_ci return "Event Data"; 145362306a36Sopenharmony_ci case TRB_TR_NOOP: 145462306a36Sopenharmony_ci return "No-Op"; 145562306a36Sopenharmony_ci case TRB_ENABLE_SLOT: 145662306a36Sopenharmony_ci return "Enable Slot Command"; 145762306a36Sopenharmony_ci case TRB_DISABLE_SLOT: 145862306a36Sopenharmony_ci return "Disable Slot Command"; 145962306a36Sopenharmony_ci case TRB_ADDR_DEV: 146062306a36Sopenharmony_ci return "Address Device Command"; 146162306a36Sopenharmony_ci case TRB_CONFIG_EP: 146262306a36Sopenharmony_ci return "Configure Endpoint Command"; 146362306a36Sopenharmony_ci case TRB_EVAL_CONTEXT: 146462306a36Sopenharmony_ci return "Evaluate Context Command"; 146562306a36Sopenharmony_ci case TRB_RESET_EP: 146662306a36Sopenharmony_ci return "Reset Endpoint Command"; 146762306a36Sopenharmony_ci case TRB_STOP_RING: 146862306a36Sopenharmony_ci return "Stop Ring Command"; 146962306a36Sopenharmony_ci case TRB_SET_DEQ: 147062306a36Sopenharmony_ci return "Set TR Dequeue Pointer Command"; 147162306a36Sopenharmony_ci case TRB_RESET_DEV: 147262306a36Sopenharmony_ci return "Reset Device Command"; 147362306a36Sopenharmony_ci case TRB_FORCE_EVENT: 147462306a36Sopenharmony_ci return "Force Event Command"; 147562306a36Sopenharmony_ci case TRB_NEG_BANDWIDTH: 147662306a36Sopenharmony_ci return "Negotiate Bandwidth Command"; 147762306a36Sopenharmony_ci case TRB_SET_LT: 147862306a36Sopenharmony_ci return "Set Latency Tolerance Value Command"; 147962306a36Sopenharmony_ci case TRB_GET_BW: 148062306a36Sopenharmony_ci return "Get Port Bandwidth Command"; 148162306a36Sopenharmony_ci case TRB_FORCE_HEADER: 148262306a36Sopenharmony_ci return "Force Header Command"; 148362306a36Sopenharmony_ci case TRB_CMD_NOOP: 148462306a36Sopenharmony_ci return "No-Op Command"; 148562306a36Sopenharmony_ci case TRB_TRANSFER: 148662306a36Sopenharmony_ci return "Transfer Event"; 148762306a36Sopenharmony_ci case TRB_COMPLETION: 148862306a36Sopenharmony_ci return "Command Completion Event"; 148962306a36Sopenharmony_ci case TRB_PORT_STATUS: 149062306a36Sopenharmony_ci return "Port Status Change Event"; 149162306a36Sopenharmony_ci case TRB_BANDWIDTH_EVENT: 149262306a36Sopenharmony_ci return "Bandwidth Request Event"; 149362306a36Sopenharmony_ci case TRB_DOORBELL: 149462306a36Sopenharmony_ci return "Doorbell Event"; 149562306a36Sopenharmony_ci case TRB_HC_EVENT: 149662306a36Sopenharmony_ci return "Host Controller Event"; 149762306a36Sopenharmony_ci case TRB_DEV_NOTE: 149862306a36Sopenharmony_ci return "Device Notification Event"; 149962306a36Sopenharmony_ci case TRB_MFINDEX_WRAP: 150062306a36Sopenharmony_ci return "MFINDEX Wrap Event"; 150162306a36Sopenharmony_ci case TRB_NEC_CMD_COMP: 150262306a36Sopenharmony_ci return "NEC Command Completion Event"; 150362306a36Sopenharmony_ci case TRB_NEC_GET_FW: 150462306a36Sopenharmony_ci return "NET Get Firmware Revision Command"; 150562306a36Sopenharmony_ci default: 150662306a36Sopenharmony_ci return "UNKNOWN"; 150762306a36Sopenharmony_ci } 150862306a36Sopenharmony_ci} 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci#define TRB_TYPE_LINK(x) (((x) & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK)) 151162306a36Sopenharmony_ci/* Above, but for __le32 types -- can avoid work by swapping constants: */ 151262306a36Sopenharmony_ci#define TRB_TYPE_LINK_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ 151362306a36Sopenharmony_ci cpu_to_le32(TRB_TYPE(TRB_LINK))) 151462306a36Sopenharmony_ci#define TRB_TYPE_NOOP_LE32(x) (((x) & cpu_to_le32(TRB_TYPE_BITMASK)) == \ 151562306a36Sopenharmony_ci cpu_to_le32(TRB_TYPE(TRB_TR_NOOP))) 151662306a36Sopenharmony_ci 151762306a36Sopenharmony_ci#define NEC_FW_MINOR(p) (((p) >> 0) & 0xff) 151862306a36Sopenharmony_ci#define NEC_FW_MAJOR(p) (((p) >> 8) & 0xff) 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci/* 152162306a36Sopenharmony_ci * TRBS_PER_SEGMENT must be a multiple of 4, 152262306a36Sopenharmony_ci * since the command ring is 64-byte aligned. 152362306a36Sopenharmony_ci * It must also be greater than 16. 152462306a36Sopenharmony_ci */ 152562306a36Sopenharmony_ci#define TRBS_PER_SEGMENT 256 152662306a36Sopenharmony_ci/* Allow two commands + a link TRB, along with any reserved command TRBs */ 152762306a36Sopenharmony_ci#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) 152862306a36Sopenharmony_ci#define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16) 152962306a36Sopenharmony_ci#define TRB_SEGMENT_SHIFT (ilog2(TRB_SEGMENT_SIZE)) 153062306a36Sopenharmony_ci/* TRB buffer pointers can't cross 64KB boundaries */ 153162306a36Sopenharmony_ci#define TRB_MAX_BUFF_SHIFT 16 153262306a36Sopenharmony_ci#define TRB_MAX_BUFF_SIZE (1 << TRB_MAX_BUFF_SHIFT) 153362306a36Sopenharmony_ci/* How much data is left before the 64KB boundary? */ 153462306a36Sopenharmony_ci#define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr) (TRB_MAX_BUFF_SIZE - \ 153562306a36Sopenharmony_ci (addr & (TRB_MAX_BUFF_SIZE - 1))) 153662306a36Sopenharmony_ci#define MAX_SOFT_RETRY 3 153762306a36Sopenharmony_ci/* 153862306a36Sopenharmony_ci * Limits of consecutive isoc trbs that can Block Event Interrupt (BEI) if 153962306a36Sopenharmony_ci * XHCI_AVOID_BEI quirk is in use. 154062306a36Sopenharmony_ci */ 154162306a36Sopenharmony_ci#define AVOID_BEI_INTERVAL_MIN 8 154262306a36Sopenharmony_ci#define AVOID_BEI_INTERVAL_MAX 32 154362306a36Sopenharmony_ci 154462306a36Sopenharmony_cistruct xhci_segment { 154562306a36Sopenharmony_ci union xhci_trb *trbs; 154662306a36Sopenharmony_ci /* private to HCD */ 154762306a36Sopenharmony_ci struct xhci_segment *next; 154862306a36Sopenharmony_ci dma_addr_t dma; 154962306a36Sopenharmony_ci /* Max packet sized bounce buffer for td-fragmant alignment */ 155062306a36Sopenharmony_ci dma_addr_t bounce_dma; 155162306a36Sopenharmony_ci void *bounce_buf; 155262306a36Sopenharmony_ci unsigned int bounce_offs; 155362306a36Sopenharmony_ci unsigned int bounce_len; 155462306a36Sopenharmony_ci}; 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_cienum xhci_cancelled_td_status { 155762306a36Sopenharmony_ci TD_DIRTY = 0, 155862306a36Sopenharmony_ci TD_HALTED, 155962306a36Sopenharmony_ci TD_CLEARING_CACHE, 156062306a36Sopenharmony_ci TD_CLEARED, 156162306a36Sopenharmony_ci}; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_cistruct xhci_td { 156462306a36Sopenharmony_ci struct list_head td_list; 156562306a36Sopenharmony_ci struct list_head cancelled_td_list; 156662306a36Sopenharmony_ci int status; 156762306a36Sopenharmony_ci enum xhci_cancelled_td_status cancel_status; 156862306a36Sopenharmony_ci struct urb *urb; 156962306a36Sopenharmony_ci struct xhci_segment *start_seg; 157062306a36Sopenharmony_ci union xhci_trb *first_trb; 157162306a36Sopenharmony_ci union xhci_trb *last_trb; 157262306a36Sopenharmony_ci struct xhci_segment *last_trb_seg; 157362306a36Sopenharmony_ci struct xhci_segment *bounce_seg; 157462306a36Sopenharmony_ci /* actual_length of the URB has already been set */ 157562306a36Sopenharmony_ci bool urb_length_set; 157662306a36Sopenharmony_ci bool error_mid_td; 157762306a36Sopenharmony_ci unsigned int num_trbs; 157862306a36Sopenharmony_ci}; 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci/* xHCI command default timeout value */ 158162306a36Sopenharmony_ci#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ) 158262306a36Sopenharmony_ci 158362306a36Sopenharmony_ci/* command descriptor */ 158462306a36Sopenharmony_cistruct xhci_cd { 158562306a36Sopenharmony_ci struct xhci_command *command; 158662306a36Sopenharmony_ci union xhci_trb *cmd_trb; 158762306a36Sopenharmony_ci}; 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_cienum xhci_ring_type { 159062306a36Sopenharmony_ci TYPE_CTRL = 0, 159162306a36Sopenharmony_ci TYPE_ISOC, 159262306a36Sopenharmony_ci TYPE_BULK, 159362306a36Sopenharmony_ci TYPE_INTR, 159462306a36Sopenharmony_ci TYPE_STREAM, 159562306a36Sopenharmony_ci TYPE_COMMAND, 159662306a36Sopenharmony_ci TYPE_EVENT, 159762306a36Sopenharmony_ci}; 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_cistatic inline const char *xhci_ring_type_string(enum xhci_ring_type type) 160062306a36Sopenharmony_ci{ 160162306a36Sopenharmony_ci switch (type) { 160262306a36Sopenharmony_ci case TYPE_CTRL: 160362306a36Sopenharmony_ci return "CTRL"; 160462306a36Sopenharmony_ci case TYPE_ISOC: 160562306a36Sopenharmony_ci return "ISOC"; 160662306a36Sopenharmony_ci case TYPE_BULK: 160762306a36Sopenharmony_ci return "BULK"; 160862306a36Sopenharmony_ci case TYPE_INTR: 160962306a36Sopenharmony_ci return "INTR"; 161062306a36Sopenharmony_ci case TYPE_STREAM: 161162306a36Sopenharmony_ci return "STREAM"; 161262306a36Sopenharmony_ci case TYPE_COMMAND: 161362306a36Sopenharmony_ci return "CMD"; 161462306a36Sopenharmony_ci case TYPE_EVENT: 161562306a36Sopenharmony_ci return "EVENT"; 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci return "UNKNOWN"; 161962306a36Sopenharmony_ci} 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_cistruct xhci_ring { 162262306a36Sopenharmony_ci struct xhci_segment *first_seg; 162362306a36Sopenharmony_ci struct xhci_segment *last_seg; 162462306a36Sopenharmony_ci union xhci_trb *enqueue; 162562306a36Sopenharmony_ci struct xhci_segment *enq_seg; 162662306a36Sopenharmony_ci union xhci_trb *dequeue; 162762306a36Sopenharmony_ci struct xhci_segment *deq_seg; 162862306a36Sopenharmony_ci struct list_head td_list; 162962306a36Sopenharmony_ci /* 163062306a36Sopenharmony_ci * Write the cycle state into the TRB cycle field to give ownership of 163162306a36Sopenharmony_ci * the TRB to the host controller (if we are the producer), or to check 163262306a36Sopenharmony_ci * if we own the TRB (if we are the consumer). See section 4.9.1. 163362306a36Sopenharmony_ci */ 163462306a36Sopenharmony_ci u32 cycle_state; 163562306a36Sopenharmony_ci unsigned int stream_id; 163662306a36Sopenharmony_ci unsigned int num_segs; 163762306a36Sopenharmony_ci unsigned int num_trbs_free; /* used only by xhci DbC */ 163862306a36Sopenharmony_ci unsigned int bounce_buf_len; 163962306a36Sopenharmony_ci enum xhci_ring_type type; 164062306a36Sopenharmony_ci bool last_td_was_short; 164162306a36Sopenharmony_ci struct radix_tree_root *trb_address_map; 164262306a36Sopenharmony_ci}; 164362306a36Sopenharmony_ci 164462306a36Sopenharmony_cistruct xhci_erst_entry { 164562306a36Sopenharmony_ci /* 64-bit event ring segment address */ 164662306a36Sopenharmony_ci __le64 seg_addr; 164762306a36Sopenharmony_ci __le32 seg_size; 164862306a36Sopenharmony_ci /* Set to zero */ 164962306a36Sopenharmony_ci __le32 rsvd; 165062306a36Sopenharmony_ci}; 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_cistruct xhci_erst { 165362306a36Sopenharmony_ci struct xhci_erst_entry *entries; 165462306a36Sopenharmony_ci unsigned int num_entries; 165562306a36Sopenharmony_ci /* xhci->event_ring keeps track of segment dma addresses */ 165662306a36Sopenharmony_ci dma_addr_t erst_dma_addr; 165762306a36Sopenharmony_ci /* Num entries the ERST can contain */ 165862306a36Sopenharmony_ci unsigned int erst_size; 165962306a36Sopenharmony_ci}; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_cistruct xhci_scratchpad { 166262306a36Sopenharmony_ci u64 *sp_array; 166362306a36Sopenharmony_ci dma_addr_t sp_dma; 166462306a36Sopenharmony_ci void **sp_buffers; 166562306a36Sopenharmony_ci}; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_cistruct urb_priv { 166862306a36Sopenharmony_ci int num_tds; 166962306a36Sopenharmony_ci int num_tds_done; 167062306a36Sopenharmony_ci struct xhci_td td[]; 167162306a36Sopenharmony_ci}; 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci/* 167462306a36Sopenharmony_ci * Each segment table entry is 4*32bits long. 1K seems like an ok size: 167562306a36Sopenharmony_ci * (1K bytes * 8bytes/bit) / (4*32 bits) = 64 segment entries in the table, 167662306a36Sopenharmony_ci * meaning 64 ring segments. 167762306a36Sopenharmony_ci * Initial allocated size of the ERST, in number of entries */ 167862306a36Sopenharmony_ci#define ERST_NUM_SEGS 1 167962306a36Sopenharmony_ci/* Poll every 60 seconds */ 168062306a36Sopenharmony_ci#define POLL_TIMEOUT 60 168162306a36Sopenharmony_ci/* Stop endpoint command timeout (secs) for URB cancellation watchdog timer */ 168262306a36Sopenharmony_ci#define XHCI_STOP_EP_CMD_TIMEOUT 5 168362306a36Sopenharmony_ci/* XXX: Make these module parameters */ 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_cistruct s3_save { 168662306a36Sopenharmony_ci u32 command; 168762306a36Sopenharmony_ci u32 dev_nt; 168862306a36Sopenharmony_ci u64 dcbaa_ptr; 168962306a36Sopenharmony_ci u32 config_reg; 169062306a36Sopenharmony_ci}; 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci/* Use for lpm */ 169362306a36Sopenharmony_cistruct dev_info { 169462306a36Sopenharmony_ci u32 dev_id; 169562306a36Sopenharmony_ci struct list_head list; 169662306a36Sopenharmony_ci}; 169762306a36Sopenharmony_ci 169862306a36Sopenharmony_cistruct xhci_bus_state { 169962306a36Sopenharmony_ci unsigned long bus_suspended; 170062306a36Sopenharmony_ci unsigned long next_statechange; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci /* Port suspend arrays are indexed by the portnum of the fake roothub */ 170362306a36Sopenharmony_ci /* ports suspend status arrays - max 31 ports for USB2, 15 for USB3 */ 170462306a36Sopenharmony_ci u32 port_c_suspend; 170562306a36Sopenharmony_ci u32 suspended_ports; 170662306a36Sopenharmony_ci u32 port_remote_wakeup; 170762306a36Sopenharmony_ci /* which ports have started to resume */ 170862306a36Sopenharmony_ci unsigned long resuming_ports; 170962306a36Sopenharmony_ci}; 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_cistruct xhci_interrupter { 171262306a36Sopenharmony_ci struct xhci_ring *event_ring; 171362306a36Sopenharmony_ci struct xhci_erst erst; 171462306a36Sopenharmony_ci struct xhci_intr_reg __iomem *ir_set; 171562306a36Sopenharmony_ci unsigned int intr_num; 171662306a36Sopenharmony_ci /* For interrupter registers save and restore over suspend/resume */ 171762306a36Sopenharmony_ci u32 s3_irq_pending; 171862306a36Sopenharmony_ci u32 s3_irq_control; 171962306a36Sopenharmony_ci u32 s3_erst_size; 172062306a36Sopenharmony_ci u64 s3_erst_base; 172162306a36Sopenharmony_ci u64 s3_erst_dequeue; 172262306a36Sopenharmony_ci}; 172362306a36Sopenharmony_ci/* 172462306a36Sopenharmony_ci * It can take up to 20 ms to transition from RExit to U0 on the 172562306a36Sopenharmony_ci * Intel Lynx Point LP xHCI host. 172662306a36Sopenharmony_ci */ 172762306a36Sopenharmony_ci#define XHCI_MAX_REXIT_TIMEOUT_MS 20 172862306a36Sopenharmony_cistruct xhci_port_cap { 172962306a36Sopenharmony_ci u32 *psi; /* array of protocol speed ID entries */ 173062306a36Sopenharmony_ci u8 psi_count; 173162306a36Sopenharmony_ci u8 psi_uid_count; 173262306a36Sopenharmony_ci u8 maj_rev; 173362306a36Sopenharmony_ci u8 min_rev; 173462306a36Sopenharmony_ci}; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_cistruct xhci_port { 173762306a36Sopenharmony_ci __le32 __iomem *addr; 173862306a36Sopenharmony_ci int hw_portnum; 173962306a36Sopenharmony_ci int hcd_portnum; 174062306a36Sopenharmony_ci struct xhci_hub *rhub; 174162306a36Sopenharmony_ci struct xhci_port_cap *port_cap; 174262306a36Sopenharmony_ci unsigned int lpm_incapable:1; 174362306a36Sopenharmony_ci unsigned long resume_timestamp; 174462306a36Sopenharmony_ci bool rexit_active; 174562306a36Sopenharmony_ci struct completion rexit_done; 174662306a36Sopenharmony_ci struct completion u3exit_done; 174762306a36Sopenharmony_ci}; 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_cistruct xhci_hub { 175062306a36Sopenharmony_ci struct xhci_port **ports; 175162306a36Sopenharmony_ci unsigned int num_ports; 175262306a36Sopenharmony_ci struct usb_hcd *hcd; 175362306a36Sopenharmony_ci /* keep track of bus suspend info */ 175462306a36Sopenharmony_ci struct xhci_bus_state bus_state; 175562306a36Sopenharmony_ci /* supported prococol extended capabiliy values */ 175662306a36Sopenharmony_ci u8 maj_rev; 175762306a36Sopenharmony_ci u8 min_rev; 175862306a36Sopenharmony_ci}; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci/* There is one xhci_hcd structure per controller */ 176162306a36Sopenharmony_cistruct xhci_hcd { 176262306a36Sopenharmony_ci struct usb_hcd *main_hcd; 176362306a36Sopenharmony_ci struct usb_hcd *shared_hcd; 176462306a36Sopenharmony_ci /* glue to PCI and HCD framework */ 176562306a36Sopenharmony_ci struct xhci_cap_regs __iomem *cap_regs; 176662306a36Sopenharmony_ci struct xhci_op_regs __iomem *op_regs; 176762306a36Sopenharmony_ci struct xhci_run_regs __iomem *run_regs; 176862306a36Sopenharmony_ci struct xhci_doorbell_array __iomem *dba; 176962306a36Sopenharmony_ci 177062306a36Sopenharmony_ci /* Cached register copies of read-only HC data */ 177162306a36Sopenharmony_ci __u32 hcs_params1; 177262306a36Sopenharmony_ci __u32 hcs_params2; 177362306a36Sopenharmony_ci __u32 hcs_params3; 177462306a36Sopenharmony_ci __u32 hcc_params; 177562306a36Sopenharmony_ci __u32 hcc_params2; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci spinlock_t lock; 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci /* packed release number */ 178062306a36Sopenharmony_ci u8 sbrn; 178162306a36Sopenharmony_ci u16 hci_version; 178262306a36Sopenharmony_ci u8 max_slots; 178362306a36Sopenharmony_ci u16 max_interrupters; 178462306a36Sopenharmony_ci u8 max_ports; 178562306a36Sopenharmony_ci u8 isoc_threshold; 178662306a36Sopenharmony_ci /* imod_interval in ns (I * 250ns) */ 178762306a36Sopenharmony_ci u32 imod_interval; 178862306a36Sopenharmony_ci u32 isoc_bei_interval; 178962306a36Sopenharmony_ci int event_ring_max; 179062306a36Sopenharmony_ci /* 4KB min, 128MB max */ 179162306a36Sopenharmony_ci int page_size; 179262306a36Sopenharmony_ci /* Valid values are 12 to 20, inclusive */ 179362306a36Sopenharmony_ci int page_shift; 179462306a36Sopenharmony_ci /* msi-x vectors */ 179562306a36Sopenharmony_ci int msix_count; 179662306a36Sopenharmony_ci /* optional clocks */ 179762306a36Sopenharmony_ci struct clk *clk; 179862306a36Sopenharmony_ci struct clk *reg_clk; 179962306a36Sopenharmony_ci /* optional reset controller */ 180062306a36Sopenharmony_ci struct reset_control *reset; 180162306a36Sopenharmony_ci /* data structures */ 180262306a36Sopenharmony_ci struct xhci_device_context_array *dcbaa; 180362306a36Sopenharmony_ci struct xhci_interrupter *interrupter; 180462306a36Sopenharmony_ci struct xhci_ring *cmd_ring; 180562306a36Sopenharmony_ci unsigned int cmd_ring_state; 180662306a36Sopenharmony_ci#define CMD_RING_STATE_RUNNING (1 << 0) 180762306a36Sopenharmony_ci#define CMD_RING_STATE_ABORTED (1 << 1) 180862306a36Sopenharmony_ci#define CMD_RING_STATE_STOPPED (1 << 2) 180962306a36Sopenharmony_ci struct list_head cmd_list; 181062306a36Sopenharmony_ci unsigned int cmd_ring_reserved_trbs; 181162306a36Sopenharmony_ci struct delayed_work cmd_timer; 181262306a36Sopenharmony_ci struct completion cmd_ring_stop_completion; 181362306a36Sopenharmony_ci struct xhci_command *current_cmd; 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci /* Scratchpad */ 181662306a36Sopenharmony_ci struct xhci_scratchpad *scratchpad; 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci /* slot enabling and address device helpers */ 181962306a36Sopenharmony_ci /* these are not thread safe so use mutex */ 182062306a36Sopenharmony_ci struct mutex mutex; 182162306a36Sopenharmony_ci /* Internal mirror of the HW's dcbaa */ 182262306a36Sopenharmony_ci struct xhci_virt_device *devs[MAX_HC_SLOTS]; 182362306a36Sopenharmony_ci /* For keeping track of bandwidth domains per roothub. */ 182462306a36Sopenharmony_ci struct xhci_root_port_bw_info *rh_bw; 182562306a36Sopenharmony_ci 182662306a36Sopenharmony_ci /* DMA pools */ 182762306a36Sopenharmony_ci struct dma_pool *device_pool; 182862306a36Sopenharmony_ci struct dma_pool *segment_pool; 182962306a36Sopenharmony_ci struct dma_pool *small_streams_pool; 183062306a36Sopenharmony_ci struct dma_pool *medium_streams_pool; 183162306a36Sopenharmony_ci 183262306a36Sopenharmony_ci /* Host controller watchdog timer structures */ 183362306a36Sopenharmony_ci unsigned int xhc_state; 183462306a36Sopenharmony_ci unsigned long run_graceperiod; 183562306a36Sopenharmony_ci struct s3_save s3; 183662306a36Sopenharmony_ci/* Host controller is dying - not responding to commands. "I'm not dead yet!" 183762306a36Sopenharmony_ci * 183862306a36Sopenharmony_ci * xHC interrupts have been disabled and a watchdog timer will (or has already) 183962306a36Sopenharmony_ci * halt the xHCI host, and complete all URBs with an -ESHUTDOWN code. Any code 184062306a36Sopenharmony_ci * that sees this status (other than the timer that set it) should stop touching 184162306a36Sopenharmony_ci * hardware immediately. Interrupt handlers should return immediately when 184262306a36Sopenharmony_ci * they see this status (any time they drop and re-acquire xhci->lock). 184362306a36Sopenharmony_ci * xhci_urb_dequeue() should call usb_hcd_check_unlink_urb() and return without 184462306a36Sopenharmony_ci * putting the TD on the canceled list, etc. 184562306a36Sopenharmony_ci * 184662306a36Sopenharmony_ci * There are no reports of xHCI host controllers that display this issue. 184762306a36Sopenharmony_ci */ 184862306a36Sopenharmony_ci#define XHCI_STATE_DYING (1 << 0) 184962306a36Sopenharmony_ci#define XHCI_STATE_HALTED (1 << 1) 185062306a36Sopenharmony_ci#define XHCI_STATE_REMOVING (1 << 2) 185162306a36Sopenharmony_ci unsigned long long quirks; 185262306a36Sopenharmony_ci#define XHCI_LINK_TRB_QUIRK BIT_ULL(0) 185362306a36Sopenharmony_ci#define XHCI_RESET_EP_QUIRK BIT_ULL(1) /* Deprecated */ 185462306a36Sopenharmony_ci#define XHCI_NEC_HOST BIT_ULL(2) 185562306a36Sopenharmony_ci#define XHCI_AMD_PLL_FIX BIT_ULL(3) 185662306a36Sopenharmony_ci#define XHCI_SPURIOUS_SUCCESS BIT_ULL(4) 185762306a36Sopenharmony_ci/* 185862306a36Sopenharmony_ci * Certain Intel host controllers have a limit to the number of endpoint 185962306a36Sopenharmony_ci * contexts they can handle. Ideally, they would signal that they can't handle 186062306a36Sopenharmony_ci * anymore endpoint contexts by returning a Resource Error for the Configure 186162306a36Sopenharmony_ci * Endpoint command, but they don't. Instead they expect software to keep track 186262306a36Sopenharmony_ci * of the number of active endpoints for them, across configure endpoint 186362306a36Sopenharmony_ci * commands, reset device commands, disable slot commands, and address device 186462306a36Sopenharmony_ci * commands. 186562306a36Sopenharmony_ci */ 186662306a36Sopenharmony_ci#define XHCI_EP_LIMIT_QUIRK BIT_ULL(5) 186762306a36Sopenharmony_ci#define XHCI_BROKEN_MSI BIT_ULL(6) 186862306a36Sopenharmony_ci#define XHCI_RESET_ON_RESUME BIT_ULL(7) 186962306a36Sopenharmony_ci#define XHCI_SW_BW_CHECKING BIT_ULL(8) 187062306a36Sopenharmony_ci#define XHCI_AMD_0x96_HOST BIT_ULL(9) 187162306a36Sopenharmony_ci#define XHCI_TRUST_TX_LENGTH BIT_ULL(10) 187262306a36Sopenharmony_ci#define XHCI_LPM_SUPPORT BIT_ULL(11) 187362306a36Sopenharmony_ci#define XHCI_INTEL_HOST BIT_ULL(12) 187462306a36Sopenharmony_ci#define XHCI_SPURIOUS_REBOOT BIT_ULL(13) 187562306a36Sopenharmony_ci#define XHCI_COMP_MODE_QUIRK BIT_ULL(14) 187662306a36Sopenharmony_ci#define XHCI_AVOID_BEI BIT_ULL(15) 187762306a36Sopenharmony_ci#define XHCI_PLAT BIT_ULL(16) /* Deprecated */ 187862306a36Sopenharmony_ci#define XHCI_SLOW_SUSPEND BIT_ULL(17) 187962306a36Sopenharmony_ci#define XHCI_SPURIOUS_WAKEUP BIT_ULL(18) 188062306a36Sopenharmony_ci/* For controllers with a broken beyond repair streams implementation */ 188162306a36Sopenharmony_ci#define XHCI_BROKEN_STREAMS BIT_ULL(19) 188262306a36Sopenharmony_ci#define XHCI_PME_STUCK_QUIRK BIT_ULL(20) 188362306a36Sopenharmony_ci#define XHCI_MTK_HOST BIT_ULL(21) 188462306a36Sopenharmony_ci#define XHCI_SSIC_PORT_UNUSED BIT_ULL(22) 188562306a36Sopenharmony_ci#define XHCI_NO_64BIT_SUPPORT BIT_ULL(23) 188662306a36Sopenharmony_ci#define XHCI_MISSING_CAS BIT_ULL(24) 188762306a36Sopenharmony_ci/* For controller with a broken Port Disable implementation */ 188862306a36Sopenharmony_ci#define XHCI_BROKEN_PORT_PED BIT_ULL(25) 188962306a36Sopenharmony_ci#define XHCI_LIMIT_ENDPOINT_INTERVAL_7 BIT_ULL(26) 189062306a36Sopenharmony_ci#define XHCI_U2_DISABLE_WAKE BIT_ULL(27) 189162306a36Sopenharmony_ci#define XHCI_ASMEDIA_MODIFY_FLOWCONTROL BIT_ULL(28) 189262306a36Sopenharmony_ci#define XHCI_HW_LPM_DISABLE BIT_ULL(29) 189362306a36Sopenharmony_ci#define XHCI_SUSPEND_DELAY BIT_ULL(30) 189462306a36Sopenharmony_ci#define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31) 189562306a36Sopenharmony_ci#define XHCI_ZERO_64B_REGS BIT_ULL(32) 189662306a36Sopenharmony_ci#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) 189762306a36Sopenharmony_ci#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) 189862306a36Sopenharmony_ci#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35) 189962306a36Sopenharmony_ci#define XHCI_RENESAS_FW_QUIRK BIT_ULL(36) 190062306a36Sopenharmony_ci#define XHCI_SKIP_PHY_INIT BIT_ULL(37) 190162306a36Sopenharmony_ci#define XHCI_DISABLE_SPARSE BIT_ULL(38) 190262306a36Sopenharmony_ci#define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) 190362306a36Sopenharmony_ci#define XHCI_NO_SOFT_RETRY BIT_ULL(40) 190462306a36Sopenharmony_ci#define XHCI_BROKEN_D3COLD_S2I BIT_ULL(41) 190562306a36Sopenharmony_ci#define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) 190662306a36Sopenharmony_ci#define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) 190762306a36Sopenharmony_ci#define XHCI_RESET_TO_DEFAULT BIT_ULL(44) 190862306a36Sopenharmony_ci#define XHCI_ZHAOXIN_TRB_FETCH BIT_ULL(45) 190962306a36Sopenharmony_ci#define XHCI_ZHAOXIN_HOST BIT_ULL(46) 191062306a36Sopenharmony_ci 191162306a36Sopenharmony_ci unsigned int num_active_eps; 191262306a36Sopenharmony_ci unsigned int limit_active_eps; 191362306a36Sopenharmony_ci struct xhci_port *hw_ports; 191462306a36Sopenharmony_ci struct xhci_hub usb2_rhub; 191562306a36Sopenharmony_ci struct xhci_hub usb3_rhub; 191662306a36Sopenharmony_ci /* support xHCI 1.0 spec USB2 hardware LPM */ 191762306a36Sopenharmony_ci unsigned hw_lpm_support:1; 191862306a36Sopenharmony_ci /* Broken Suspend flag for SNPS Suspend resume issue */ 191962306a36Sopenharmony_ci unsigned broken_suspend:1; 192062306a36Sopenharmony_ci /* Indicates that omitting hcd is supported if root hub has no ports */ 192162306a36Sopenharmony_ci unsigned allow_single_roothub:1; 192262306a36Sopenharmony_ci /* cached usb2 extened protocol capabilites */ 192362306a36Sopenharmony_ci u32 *ext_caps; 192462306a36Sopenharmony_ci unsigned int num_ext_caps; 192562306a36Sopenharmony_ci /* cached extended protocol port capabilities */ 192662306a36Sopenharmony_ci struct xhci_port_cap *port_caps; 192762306a36Sopenharmony_ci unsigned int num_port_caps; 192862306a36Sopenharmony_ci /* Compliance Mode Recovery Data */ 192962306a36Sopenharmony_ci struct timer_list comp_mode_recovery_timer; 193062306a36Sopenharmony_ci u32 port_status_u0; 193162306a36Sopenharmony_ci u16 test_mode; 193262306a36Sopenharmony_ci/* Compliance Mode Timer Triggered every 2 seconds */ 193362306a36Sopenharmony_ci#define COMP_MODE_RCVRY_MSECS 2000 193462306a36Sopenharmony_ci 193562306a36Sopenharmony_ci struct dentry *debugfs_root; 193662306a36Sopenharmony_ci struct dentry *debugfs_slots; 193762306a36Sopenharmony_ci struct list_head regset_list; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci void *dbc; 194062306a36Sopenharmony_ci /* platform-specific data -- must come last */ 194162306a36Sopenharmony_ci unsigned long priv[] __aligned(sizeof(s64)); 194262306a36Sopenharmony_ci}; 194362306a36Sopenharmony_ci 194462306a36Sopenharmony_ci/* Platform specific overrides to generic XHCI hc_driver ops */ 194562306a36Sopenharmony_cistruct xhci_driver_overrides { 194662306a36Sopenharmony_ci size_t extra_priv_size; 194762306a36Sopenharmony_ci int (*reset)(struct usb_hcd *hcd); 194862306a36Sopenharmony_ci int (*start)(struct usb_hcd *hcd); 194962306a36Sopenharmony_ci int (*add_endpoint)(struct usb_hcd *hcd, struct usb_device *udev, 195062306a36Sopenharmony_ci struct usb_host_endpoint *ep); 195162306a36Sopenharmony_ci int (*drop_endpoint)(struct usb_hcd *hcd, struct usb_device *udev, 195262306a36Sopenharmony_ci struct usb_host_endpoint *ep); 195362306a36Sopenharmony_ci int (*check_bandwidth)(struct usb_hcd *, struct usb_device *); 195462306a36Sopenharmony_ci void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); 195562306a36Sopenharmony_ci int (*update_hub_device)(struct usb_hcd *hcd, struct usb_device *hdev, 195662306a36Sopenharmony_ci struct usb_tt *tt, gfp_t mem_flags); 195762306a36Sopenharmony_ci int (*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue, 195862306a36Sopenharmony_ci u16 wIndex, char *buf, u16 wLength); 195962306a36Sopenharmony_ci}; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci#define XHCI_CFC_DELAY 10 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci/* convert between an HCD pointer and the corresponding EHCI_HCD */ 196462306a36Sopenharmony_cistatic inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd) 196562306a36Sopenharmony_ci{ 196662306a36Sopenharmony_ci struct usb_hcd *primary_hcd; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci if (usb_hcd_is_primary_hcd(hcd)) 196962306a36Sopenharmony_ci primary_hcd = hcd; 197062306a36Sopenharmony_ci else 197162306a36Sopenharmony_ci primary_hcd = hcd->primary_hcd; 197262306a36Sopenharmony_ci 197362306a36Sopenharmony_ci return (struct xhci_hcd *) (primary_hcd->hcd_priv); 197462306a36Sopenharmony_ci} 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_cistatic inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci) 197762306a36Sopenharmony_ci{ 197862306a36Sopenharmony_ci return xhci->main_hcd; 197962306a36Sopenharmony_ci} 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_cistatic inline struct usb_hcd *xhci_get_usb3_hcd(struct xhci_hcd *xhci) 198262306a36Sopenharmony_ci{ 198362306a36Sopenharmony_ci if (xhci->shared_hcd) 198462306a36Sopenharmony_ci return xhci->shared_hcd; 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_ci if (!xhci->usb2_rhub.num_ports) 198762306a36Sopenharmony_ci return xhci->main_hcd; 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_ci return NULL; 199062306a36Sopenharmony_ci} 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_cistatic inline bool xhci_hcd_is_usb3(struct usb_hcd *hcd) 199362306a36Sopenharmony_ci{ 199462306a36Sopenharmony_ci struct xhci_hcd *xhci = hcd_to_xhci(hcd); 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci return hcd == xhci_get_usb3_hcd(xhci); 199762306a36Sopenharmony_ci} 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_cistatic inline bool xhci_has_one_roothub(struct xhci_hcd *xhci) 200062306a36Sopenharmony_ci{ 200162306a36Sopenharmony_ci return xhci->allow_single_roothub && 200262306a36Sopenharmony_ci (!xhci->usb2_rhub.num_ports || !xhci->usb3_rhub.num_ports); 200362306a36Sopenharmony_ci} 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci#define xhci_dbg(xhci, fmt, args...) \ 200662306a36Sopenharmony_ci dev_dbg(xhci_to_hcd(xhci)->self.controller , fmt , ## args) 200762306a36Sopenharmony_ci#define xhci_err(xhci, fmt, args...) \ 200862306a36Sopenharmony_ci dev_err(xhci_to_hcd(xhci)->self.controller , fmt , ## args) 200962306a36Sopenharmony_ci#define xhci_warn(xhci, fmt, args...) \ 201062306a36Sopenharmony_ci dev_warn(xhci_to_hcd(xhci)->self.controller , fmt , ## args) 201162306a36Sopenharmony_ci#define xhci_warn_ratelimited(xhci, fmt, args...) \ 201262306a36Sopenharmony_ci dev_warn_ratelimited(xhci_to_hcd(xhci)->self.controller , fmt , ## args) 201362306a36Sopenharmony_ci#define xhci_info(xhci, fmt, args...) \ 201462306a36Sopenharmony_ci dev_info(xhci_to_hcd(xhci)->self.controller , fmt , ## args) 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci/* 201762306a36Sopenharmony_ci * Registers should always be accessed with double word or quad word accesses. 201862306a36Sopenharmony_ci * 201962306a36Sopenharmony_ci * Some xHCI implementations may support 64-bit address pointers. Registers 202062306a36Sopenharmony_ci * with 64-bit address pointers should be written to with dword accesses by 202162306a36Sopenharmony_ci * writing the low dword first (ptr[0]), then the high dword (ptr[1]) second. 202262306a36Sopenharmony_ci * xHCI implementations that do not support 64-bit address pointers will ignore 202362306a36Sopenharmony_ci * the high dword, and write order is irrelevant. 202462306a36Sopenharmony_ci */ 202562306a36Sopenharmony_cistatic inline u64 xhci_read_64(const struct xhci_hcd *xhci, 202662306a36Sopenharmony_ci __le64 __iomem *regs) 202762306a36Sopenharmony_ci{ 202862306a36Sopenharmony_ci return lo_hi_readq(regs); 202962306a36Sopenharmony_ci} 203062306a36Sopenharmony_cistatic inline void xhci_write_64(struct xhci_hcd *xhci, 203162306a36Sopenharmony_ci const u64 val, __le64 __iomem *regs) 203262306a36Sopenharmony_ci{ 203362306a36Sopenharmony_ci lo_hi_writeq(val, regs); 203462306a36Sopenharmony_ci} 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_cistatic inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) 203762306a36Sopenharmony_ci{ 203862306a36Sopenharmony_ci return xhci->quirks & XHCI_LINK_TRB_QUIRK; 203962306a36Sopenharmony_ci} 204062306a36Sopenharmony_ci 204162306a36Sopenharmony_ci/* xHCI debugging */ 204262306a36Sopenharmony_cichar *xhci_get_slot_state(struct xhci_hcd *xhci, 204362306a36Sopenharmony_ci struct xhci_container_ctx *ctx); 204462306a36Sopenharmony_civoid xhci_dbg_trace(struct xhci_hcd *xhci, void (*trace)(struct va_format *), 204562306a36Sopenharmony_ci const char *fmt, ...); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci/* xHCI memory management */ 204862306a36Sopenharmony_civoid xhci_mem_cleanup(struct xhci_hcd *xhci); 204962306a36Sopenharmony_ciint xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags); 205062306a36Sopenharmony_civoid xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id); 205162306a36Sopenharmony_ciint xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags); 205262306a36Sopenharmony_ciint xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); 205362306a36Sopenharmony_civoid xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, 205462306a36Sopenharmony_ci struct usb_device *udev); 205562306a36Sopenharmony_ciunsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); 205662306a36Sopenharmony_ciunsigned int xhci_last_valid_endpoint(u32 added_ctxs); 205762306a36Sopenharmony_civoid xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); 205862306a36Sopenharmony_civoid xhci_update_tt_active_eps(struct xhci_hcd *xhci, 205962306a36Sopenharmony_ci struct xhci_virt_device *virt_dev, 206062306a36Sopenharmony_ci int old_active_eps); 206162306a36Sopenharmony_civoid xhci_clear_endpoint_bw_info(struct xhci_bw_info *bw_info); 206262306a36Sopenharmony_civoid xhci_update_bw_info(struct xhci_hcd *xhci, 206362306a36Sopenharmony_ci struct xhci_container_ctx *in_ctx, 206462306a36Sopenharmony_ci struct xhci_input_control_ctx *ctrl_ctx, 206562306a36Sopenharmony_ci struct xhci_virt_device *virt_dev); 206662306a36Sopenharmony_civoid xhci_endpoint_copy(struct xhci_hcd *xhci, 206762306a36Sopenharmony_ci struct xhci_container_ctx *in_ctx, 206862306a36Sopenharmony_ci struct xhci_container_ctx *out_ctx, 206962306a36Sopenharmony_ci unsigned int ep_index); 207062306a36Sopenharmony_civoid xhci_slot_copy(struct xhci_hcd *xhci, 207162306a36Sopenharmony_ci struct xhci_container_ctx *in_ctx, 207262306a36Sopenharmony_ci struct xhci_container_ctx *out_ctx); 207362306a36Sopenharmony_ciint xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, 207462306a36Sopenharmony_ci struct usb_device *udev, struct usb_host_endpoint *ep, 207562306a36Sopenharmony_ci gfp_t mem_flags); 207662306a36Sopenharmony_cistruct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, 207762306a36Sopenharmony_ci unsigned int num_segs, unsigned int cycle_state, 207862306a36Sopenharmony_ci enum xhci_ring_type type, unsigned int max_packet, gfp_t flags); 207962306a36Sopenharmony_civoid xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring); 208062306a36Sopenharmony_ciint xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring, 208162306a36Sopenharmony_ci unsigned int num_trbs, gfp_t flags); 208262306a36Sopenharmony_ciint xhci_alloc_erst(struct xhci_hcd *xhci, 208362306a36Sopenharmony_ci struct xhci_ring *evt_ring, 208462306a36Sopenharmony_ci struct xhci_erst *erst, 208562306a36Sopenharmony_ci gfp_t flags); 208662306a36Sopenharmony_civoid xhci_initialize_ring_info(struct xhci_ring *ring, 208762306a36Sopenharmony_ci unsigned int cycle_state); 208862306a36Sopenharmony_civoid xhci_free_erst(struct xhci_hcd *xhci, struct xhci_erst *erst); 208962306a36Sopenharmony_civoid xhci_free_endpoint_ring(struct xhci_hcd *xhci, 209062306a36Sopenharmony_ci struct xhci_virt_device *virt_dev, 209162306a36Sopenharmony_ci unsigned int ep_index); 209262306a36Sopenharmony_cistruct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci, 209362306a36Sopenharmony_ci unsigned int num_stream_ctxs, 209462306a36Sopenharmony_ci unsigned int num_streams, 209562306a36Sopenharmony_ci unsigned int max_packet, gfp_t flags); 209662306a36Sopenharmony_civoid xhci_free_stream_info(struct xhci_hcd *xhci, 209762306a36Sopenharmony_ci struct xhci_stream_info *stream_info); 209862306a36Sopenharmony_civoid xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci, 209962306a36Sopenharmony_ci struct xhci_ep_ctx *ep_ctx, 210062306a36Sopenharmony_ci struct xhci_stream_info *stream_info); 210162306a36Sopenharmony_civoid xhci_setup_no_streams_ep_input_ctx(struct xhci_ep_ctx *ep_ctx, 210262306a36Sopenharmony_ci struct xhci_virt_ep *ep); 210362306a36Sopenharmony_civoid xhci_free_device_endpoint_resources(struct xhci_hcd *xhci, 210462306a36Sopenharmony_ci struct xhci_virt_device *virt_dev, bool drop_control_ep); 210562306a36Sopenharmony_cistruct xhci_ring *xhci_dma_to_transfer_ring( 210662306a36Sopenharmony_ci struct xhci_virt_ep *ep, 210762306a36Sopenharmony_ci u64 address); 210862306a36Sopenharmony_cistruct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, 210962306a36Sopenharmony_ci bool allocate_completion, gfp_t mem_flags); 211062306a36Sopenharmony_cistruct xhci_command *xhci_alloc_command_with_ctx(struct xhci_hcd *xhci, 211162306a36Sopenharmony_ci bool allocate_completion, gfp_t mem_flags); 211262306a36Sopenharmony_civoid xhci_urb_free_priv(struct urb_priv *urb_priv); 211362306a36Sopenharmony_civoid xhci_free_command(struct xhci_hcd *xhci, 211462306a36Sopenharmony_ci struct xhci_command *command); 211562306a36Sopenharmony_cistruct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci, 211662306a36Sopenharmony_ci int type, gfp_t flags); 211762306a36Sopenharmony_civoid xhci_free_container_ctx(struct xhci_hcd *xhci, 211862306a36Sopenharmony_ci struct xhci_container_ctx *ctx); 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_ci/* xHCI host controller glue */ 212162306a36Sopenharmony_citypedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); 212262306a36Sopenharmony_ciint xhci_handshake(void __iomem *ptr, u32 mask, u32 done, u64 timeout_us); 212362306a36Sopenharmony_civoid xhci_quiesce(struct xhci_hcd *xhci); 212462306a36Sopenharmony_ciint xhci_halt(struct xhci_hcd *xhci); 212562306a36Sopenharmony_ciint xhci_start(struct xhci_hcd *xhci); 212662306a36Sopenharmony_ciint xhci_reset(struct xhci_hcd *xhci, u64 timeout_us); 212762306a36Sopenharmony_ciint xhci_run(struct usb_hcd *hcd); 212862306a36Sopenharmony_ciint xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); 212962306a36Sopenharmony_civoid xhci_shutdown(struct usb_hcd *hcd); 213062306a36Sopenharmony_civoid xhci_stop(struct usb_hcd *hcd); 213162306a36Sopenharmony_civoid xhci_init_driver(struct hc_driver *drv, 213262306a36Sopenharmony_ci const struct xhci_driver_overrides *over); 213362306a36Sopenharmony_ciint xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, 213462306a36Sopenharmony_ci struct usb_host_endpoint *ep); 213562306a36Sopenharmony_ciint xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, 213662306a36Sopenharmony_ci struct usb_host_endpoint *ep); 213762306a36Sopenharmony_ciint xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); 213862306a36Sopenharmony_civoid xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev); 213962306a36Sopenharmony_ciint xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, 214062306a36Sopenharmony_ci struct usb_tt *tt, gfp_t mem_flags); 214162306a36Sopenharmony_ciint xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id); 214262306a36Sopenharmony_ciint xhci_ext_cap_init(struct xhci_hcd *xhci); 214362306a36Sopenharmony_ci 214462306a36Sopenharmony_ciint xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); 214562306a36Sopenharmony_ciint xhci_resume(struct xhci_hcd *xhci, pm_message_t msg); 214662306a36Sopenharmony_ci 214762306a36Sopenharmony_ciirqreturn_t xhci_irq(struct usb_hcd *hcd); 214862306a36Sopenharmony_ciirqreturn_t xhci_msi_irq(int irq, void *hcd); 214962306a36Sopenharmony_ciint xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); 215062306a36Sopenharmony_ciint xhci_alloc_tt_info(struct xhci_hcd *xhci, 215162306a36Sopenharmony_ci struct xhci_virt_device *virt_dev, 215262306a36Sopenharmony_ci struct usb_device *hdev, 215362306a36Sopenharmony_ci struct usb_tt *tt, gfp_t mem_flags); 215462306a36Sopenharmony_ci 215562306a36Sopenharmony_ci/* xHCI ring, segment, TRB, and TD functions */ 215662306a36Sopenharmony_cidma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb); 215762306a36Sopenharmony_cistruct xhci_segment *trb_in_td(struct xhci_hcd *xhci, 215862306a36Sopenharmony_ci struct xhci_segment *start_seg, union xhci_trb *start_trb, 215962306a36Sopenharmony_ci union xhci_trb *end_trb, dma_addr_t suspect_dma, bool debug); 216062306a36Sopenharmony_ciint xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code); 216162306a36Sopenharmony_civoid xhci_ring_cmd_db(struct xhci_hcd *xhci); 216262306a36Sopenharmony_ciint xhci_queue_slot_control(struct xhci_hcd *xhci, struct xhci_command *cmd, 216362306a36Sopenharmony_ci u32 trb_type, u32 slot_id); 216462306a36Sopenharmony_ciint xhci_queue_address_device(struct xhci_hcd *xhci, struct xhci_command *cmd, 216562306a36Sopenharmony_ci dma_addr_t in_ctx_ptr, u32 slot_id, enum xhci_setup_dev); 216662306a36Sopenharmony_ciint xhci_queue_vendor_command(struct xhci_hcd *xhci, struct xhci_command *cmd, 216762306a36Sopenharmony_ci u32 field1, u32 field2, u32 field3, u32 field4); 216862306a36Sopenharmony_ciint xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd, 216962306a36Sopenharmony_ci int slot_id, unsigned int ep_index, int suspend); 217062306a36Sopenharmony_ciint xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 217162306a36Sopenharmony_ci int slot_id, unsigned int ep_index); 217262306a36Sopenharmony_ciint xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 217362306a36Sopenharmony_ci int slot_id, unsigned int ep_index); 217462306a36Sopenharmony_ciint xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, 217562306a36Sopenharmony_ci int slot_id, unsigned int ep_index); 217662306a36Sopenharmony_ciint xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags, 217762306a36Sopenharmony_ci struct urb *urb, int slot_id, unsigned int ep_index); 217862306a36Sopenharmony_ciint xhci_queue_configure_endpoint(struct xhci_hcd *xhci, 217962306a36Sopenharmony_ci struct xhci_command *cmd, dma_addr_t in_ctx_ptr, u32 slot_id, 218062306a36Sopenharmony_ci bool command_must_succeed); 218162306a36Sopenharmony_ciint xhci_queue_evaluate_context(struct xhci_hcd *xhci, struct xhci_command *cmd, 218262306a36Sopenharmony_ci dma_addr_t in_ctx_ptr, u32 slot_id, bool command_must_succeed); 218362306a36Sopenharmony_ciint xhci_queue_reset_ep(struct xhci_hcd *xhci, struct xhci_command *cmd, 218462306a36Sopenharmony_ci int slot_id, unsigned int ep_index, 218562306a36Sopenharmony_ci enum xhci_ep_reset_type reset_type); 218662306a36Sopenharmony_ciint xhci_queue_reset_device(struct xhci_hcd *xhci, struct xhci_command *cmd, 218762306a36Sopenharmony_ci u32 slot_id); 218862306a36Sopenharmony_civoid xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, unsigned int slot_id, 218962306a36Sopenharmony_ci unsigned int ep_index, unsigned int stream_id, 219062306a36Sopenharmony_ci struct xhci_td *td); 219162306a36Sopenharmony_civoid xhci_stop_endpoint_command_watchdog(struct timer_list *t); 219262306a36Sopenharmony_civoid xhci_handle_command_timeout(struct work_struct *work); 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_civoid xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, 219562306a36Sopenharmony_ci unsigned int ep_index, unsigned int stream_id); 219662306a36Sopenharmony_civoid xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci, 219762306a36Sopenharmony_ci unsigned int slot_id, 219862306a36Sopenharmony_ci unsigned int ep_index); 219962306a36Sopenharmony_civoid xhci_cleanup_command_queue(struct xhci_hcd *xhci); 220062306a36Sopenharmony_civoid inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring); 220162306a36Sopenharmony_ciunsigned int count_trbs(u64 addr, u64 len); 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci/* xHCI roothub code */ 220462306a36Sopenharmony_civoid xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port, 220562306a36Sopenharmony_ci u32 link_state); 220662306a36Sopenharmony_civoid xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct xhci_port *port, 220762306a36Sopenharmony_ci u32 port_bit); 220862306a36Sopenharmony_ciint xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, 220962306a36Sopenharmony_ci char *buf, u16 wLength); 221062306a36Sopenharmony_ciint xhci_hub_status_data(struct usb_hcd *hcd, char *buf); 221162306a36Sopenharmony_ciint xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); 221262306a36Sopenharmony_cistruct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); 221362306a36Sopenharmony_ci 221462306a36Sopenharmony_civoid xhci_hc_died(struct xhci_hcd *xhci); 221562306a36Sopenharmony_ci 221662306a36Sopenharmony_ci#ifdef CONFIG_PM 221762306a36Sopenharmony_ciint xhci_bus_suspend(struct usb_hcd *hcd); 221862306a36Sopenharmony_ciint xhci_bus_resume(struct usb_hcd *hcd); 221962306a36Sopenharmony_ciunsigned long xhci_get_resuming_ports(struct usb_hcd *hcd); 222062306a36Sopenharmony_ci#else 222162306a36Sopenharmony_ci#define xhci_bus_suspend NULL 222262306a36Sopenharmony_ci#define xhci_bus_resume NULL 222362306a36Sopenharmony_ci#define xhci_get_resuming_ports NULL 222462306a36Sopenharmony_ci#endif /* CONFIG_PM */ 222562306a36Sopenharmony_ci 222662306a36Sopenharmony_ciu32 xhci_port_state_to_neutral(u32 state); 222762306a36Sopenharmony_ciint xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci, 222862306a36Sopenharmony_ci u16 port); 222962306a36Sopenharmony_civoid xhci_ring_device(struct xhci_hcd *xhci, int slot_id); 223062306a36Sopenharmony_ci 223162306a36Sopenharmony_ci/* xHCI contexts */ 223262306a36Sopenharmony_cistruct xhci_input_control_ctx *xhci_get_input_control_ctx(struct xhci_container_ctx *ctx); 223362306a36Sopenharmony_cistruct xhci_slot_ctx *xhci_get_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx); 223462306a36Sopenharmony_cistruct xhci_ep_ctx *xhci_get_ep_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx, unsigned int ep_index); 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_cistruct xhci_ring *xhci_triad_to_transfer_ring(struct xhci_hcd *xhci, 223762306a36Sopenharmony_ci unsigned int slot_id, unsigned int ep_index, 223862306a36Sopenharmony_ci unsigned int stream_id); 223962306a36Sopenharmony_ci 224062306a36Sopenharmony_cistatic inline struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci, 224162306a36Sopenharmony_ci struct urb *urb) 224262306a36Sopenharmony_ci{ 224362306a36Sopenharmony_ci return xhci_triad_to_transfer_ring(xhci, urb->dev->slot_id, 224462306a36Sopenharmony_ci xhci_get_endpoint_index(&urb->ep->desc), 224562306a36Sopenharmony_ci urb->stream_id); 224662306a36Sopenharmony_ci} 224762306a36Sopenharmony_ci 224862306a36Sopenharmony_ci/* 224962306a36Sopenharmony_ci * TODO: As per spec Isochronous IDT transmissions are supported. We bypass 225062306a36Sopenharmony_ci * them anyways as we where unable to find a device that matches the 225162306a36Sopenharmony_ci * constraints. 225262306a36Sopenharmony_ci */ 225362306a36Sopenharmony_cistatic inline bool xhci_urb_suitable_for_idt(struct urb *urb) 225462306a36Sopenharmony_ci{ 225562306a36Sopenharmony_ci if (!usb_endpoint_xfer_isoc(&urb->ep->desc) && usb_urb_dir_out(urb) && 225662306a36Sopenharmony_ci usb_endpoint_maxp(&urb->ep->desc) >= TRB_IDT_MAX_SIZE && 225762306a36Sopenharmony_ci urb->transfer_buffer_length <= TRB_IDT_MAX_SIZE && 225862306a36Sopenharmony_ci !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) && 225962306a36Sopenharmony_ci !urb->num_sgs) 226062306a36Sopenharmony_ci return true; 226162306a36Sopenharmony_ci 226262306a36Sopenharmony_ci return false; 226362306a36Sopenharmony_ci} 226462306a36Sopenharmony_ci 226562306a36Sopenharmony_cistatic inline char *xhci_slot_state_string(u32 state) 226662306a36Sopenharmony_ci{ 226762306a36Sopenharmony_ci switch (state) { 226862306a36Sopenharmony_ci case SLOT_STATE_ENABLED: 226962306a36Sopenharmony_ci return "enabled/disabled"; 227062306a36Sopenharmony_ci case SLOT_STATE_DEFAULT: 227162306a36Sopenharmony_ci return "default"; 227262306a36Sopenharmony_ci case SLOT_STATE_ADDRESSED: 227362306a36Sopenharmony_ci return "addressed"; 227462306a36Sopenharmony_ci case SLOT_STATE_CONFIGURED: 227562306a36Sopenharmony_ci return "configured"; 227662306a36Sopenharmony_ci default: 227762306a36Sopenharmony_ci return "reserved"; 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci} 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_cistatic inline const char *xhci_decode_trb(char *str, size_t size, 228262306a36Sopenharmony_ci u32 field0, u32 field1, u32 field2, u32 field3) 228362306a36Sopenharmony_ci{ 228462306a36Sopenharmony_ci int type = TRB_FIELD_TO_TYPE(field3); 228562306a36Sopenharmony_ci 228662306a36Sopenharmony_ci switch (type) { 228762306a36Sopenharmony_ci case TRB_LINK: 228862306a36Sopenharmony_ci snprintf(str, size, 228962306a36Sopenharmony_ci "LINK %08x%08x intr %d type '%s' flags %c:%c:%c:%c", 229062306a36Sopenharmony_ci field1, field0, GET_INTR_TARGET(field2), 229162306a36Sopenharmony_ci xhci_trb_type_string(type), 229262306a36Sopenharmony_ci field3 & TRB_IOC ? 'I' : 'i', 229362306a36Sopenharmony_ci field3 & TRB_CHAIN ? 'C' : 'c', 229462306a36Sopenharmony_ci field3 & TRB_TC ? 'T' : 't', 229562306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 229662306a36Sopenharmony_ci break; 229762306a36Sopenharmony_ci case TRB_TRANSFER: 229862306a36Sopenharmony_ci case TRB_COMPLETION: 229962306a36Sopenharmony_ci case TRB_PORT_STATUS: 230062306a36Sopenharmony_ci case TRB_BANDWIDTH_EVENT: 230162306a36Sopenharmony_ci case TRB_DOORBELL: 230262306a36Sopenharmony_ci case TRB_HC_EVENT: 230362306a36Sopenharmony_ci case TRB_DEV_NOTE: 230462306a36Sopenharmony_ci case TRB_MFINDEX_WRAP: 230562306a36Sopenharmony_ci snprintf(str, size, 230662306a36Sopenharmony_ci "TRB %08x%08x status '%s' len %d slot %d ep %d type '%s' flags %c:%c", 230762306a36Sopenharmony_ci field1, field0, 230862306a36Sopenharmony_ci xhci_trb_comp_code_string(GET_COMP_CODE(field2)), 230962306a36Sopenharmony_ci EVENT_TRB_LEN(field2), TRB_TO_SLOT_ID(field3), 231062306a36Sopenharmony_ci /* Macro decrements 1, maybe it shouldn't?!? */ 231162306a36Sopenharmony_ci TRB_TO_EP_INDEX(field3) + 1, 231262306a36Sopenharmony_ci xhci_trb_type_string(type), 231362306a36Sopenharmony_ci field3 & EVENT_DATA ? 'E' : 'e', 231462306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 231562306a36Sopenharmony_ci 231662306a36Sopenharmony_ci break; 231762306a36Sopenharmony_ci case TRB_SETUP: 231862306a36Sopenharmony_ci snprintf(str, size, 231962306a36Sopenharmony_ci "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c", 232062306a36Sopenharmony_ci field0 & 0xff, 232162306a36Sopenharmony_ci (field0 & 0xff00) >> 8, 232262306a36Sopenharmony_ci (field0 & 0xff000000) >> 24, 232362306a36Sopenharmony_ci (field0 & 0xff0000) >> 16, 232462306a36Sopenharmony_ci (field1 & 0xff00) >> 8, 232562306a36Sopenharmony_ci field1 & 0xff, 232662306a36Sopenharmony_ci (field1 & 0xff000000) >> 16 | 232762306a36Sopenharmony_ci (field1 & 0xff0000) >> 16, 232862306a36Sopenharmony_ci TRB_LEN(field2), GET_TD_SIZE(field2), 232962306a36Sopenharmony_ci GET_INTR_TARGET(field2), 233062306a36Sopenharmony_ci xhci_trb_type_string(type), 233162306a36Sopenharmony_ci field3 & TRB_IDT ? 'I' : 'i', 233262306a36Sopenharmony_ci field3 & TRB_IOC ? 'I' : 'i', 233362306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 233462306a36Sopenharmony_ci break; 233562306a36Sopenharmony_ci case TRB_DATA: 233662306a36Sopenharmony_ci snprintf(str, size, 233762306a36Sopenharmony_ci "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c", 233862306a36Sopenharmony_ci field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), 233962306a36Sopenharmony_ci GET_INTR_TARGET(field2), 234062306a36Sopenharmony_ci xhci_trb_type_string(type), 234162306a36Sopenharmony_ci field3 & TRB_IDT ? 'I' : 'i', 234262306a36Sopenharmony_ci field3 & TRB_IOC ? 'I' : 'i', 234362306a36Sopenharmony_ci field3 & TRB_CHAIN ? 'C' : 'c', 234462306a36Sopenharmony_ci field3 & TRB_NO_SNOOP ? 'S' : 's', 234562306a36Sopenharmony_ci field3 & TRB_ISP ? 'I' : 'i', 234662306a36Sopenharmony_ci field3 & TRB_ENT ? 'E' : 'e', 234762306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 234862306a36Sopenharmony_ci break; 234962306a36Sopenharmony_ci case TRB_STATUS: 235062306a36Sopenharmony_ci snprintf(str, size, 235162306a36Sopenharmony_ci "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c", 235262306a36Sopenharmony_ci field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), 235362306a36Sopenharmony_ci GET_INTR_TARGET(field2), 235462306a36Sopenharmony_ci xhci_trb_type_string(type), 235562306a36Sopenharmony_ci field3 & TRB_IOC ? 'I' : 'i', 235662306a36Sopenharmony_ci field3 & TRB_CHAIN ? 'C' : 'c', 235762306a36Sopenharmony_ci field3 & TRB_ENT ? 'E' : 'e', 235862306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 235962306a36Sopenharmony_ci break; 236062306a36Sopenharmony_ci case TRB_NORMAL: 236162306a36Sopenharmony_ci case TRB_ISOC: 236262306a36Sopenharmony_ci case TRB_EVENT_DATA: 236362306a36Sopenharmony_ci case TRB_TR_NOOP: 236462306a36Sopenharmony_ci snprintf(str, size, 236562306a36Sopenharmony_ci "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c", 236662306a36Sopenharmony_ci field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2), 236762306a36Sopenharmony_ci GET_INTR_TARGET(field2), 236862306a36Sopenharmony_ci xhci_trb_type_string(type), 236962306a36Sopenharmony_ci field3 & TRB_BEI ? 'B' : 'b', 237062306a36Sopenharmony_ci field3 & TRB_IDT ? 'I' : 'i', 237162306a36Sopenharmony_ci field3 & TRB_IOC ? 'I' : 'i', 237262306a36Sopenharmony_ci field3 & TRB_CHAIN ? 'C' : 'c', 237362306a36Sopenharmony_ci field3 & TRB_NO_SNOOP ? 'S' : 's', 237462306a36Sopenharmony_ci field3 & TRB_ISP ? 'I' : 'i', 237562306a36Sopenharmony_ci field3 & TRB_ENT ? 'E' : 'e', 237662306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 237762306a36Sopenharmony_ci break; 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci case TRB_CMD_NOOP: 238062306a36Sopenharmony_ci case TRB_ENABLE_SLOT: 238162306a36Sopenharmony_ci snprintf(str, size, 238262306a36Sopenharmony_ci "%s: flags %c", 238362306a36Sopenharmony_ci xhci_trb_type_string(type), 238462306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 238562306a36Sopenharmony_ci break; 238662306a36Sopenharmony_ci case TRB_DISABLE_SLOT: 238762306a36Sopenharmony_ci case TRB_NEG_BANDWIDTH: 238862306a36Sopenharmony_ci snprintf(str, size, 238962306a36Sopenharmony_ci "%s: slot %d flags %c", 239062306a36Sopenharmony_ci xhci_trb_type_string(type), 239162306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 239262306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 239362306a36Sopenharmony_ci break; 239462306a36Sopenharmony_ci case TRB_ADDR_DEV: 239562306a36Sopenharmony_ci snprintf(str, size, 239662306a36Sopenharmony_ci "%s: ctx %08x%08x slot %d flags %c:%c", 239762306a36Sopenharmony_ci xhci_trb_type_string(type), 239862306a36Sopenharmony_ci field1, field0, 239962306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 240062306a36Sopenharmony_ci field3 & TRB_BSR ? 'B' : 'b', 240162306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 240262306a36Sopenharmony_ci break; 240362306a36Sopenharmony_ci case TRB_CONFIG_EP: 240462306a36Sopenharmony_ci snprintf(str, size, 240562306a36Sopenharmony_ci "%s: ctx %08x%08x slot %d flags %c:%c", 240662306a36Sopenharmony_ci xhci_trb_type_string(type), 240762306a36Sopenharmony_ci field1, field0, 240862306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 240962306a36Sopenharmony_ci field3 & TRB_DC ? 'D' : 'd', 241062306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 241162306a36Sopenharmony_ci break; 241262306a36Sopenharmony_ci case TRB_EVAL_CONTEXT: 241362306a36Sopenharmony_ci snprintf(str, size, 241462306a36Sopenharmony_ci "%s: ctx %08x%08x slot %d flags %c", 241562306a36Sopenharmony_ci xhci_trb_type_string(type), 241662306a36Sopenharmony_ci field1, field0, 241762306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 241862306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 241962306a36Sopenharmony_ci break; 242062306a36Sopenharmony_ci case TRB_RESET_EP: 242162306a36Sopenharmony_ci snprintf(str, size, 242262306a36Sopenharmony_ci "%s: ctx %08x%08x slot %d ep %d flags %c:%c", 242362306a36Sopenharmony_ci xhci_trb_type_string(type), 242462306a36Sopenharmony_ci field1, field0, 242562306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 242662306a36Sopenharmony_ci /* Macro decrements 1, maybe it shouldn't?!? */ 242762306a36Sopenharmony_ci TRB_TO_EP_INDEX(field3) + 1, 242862306a36Sopenharmony_ci field3 & TRB_TSP ? 'T' : 't', 242962306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 243062306a36Sopenharmony_ci break; 243162306a36Sopenharmony_ci case TRB_STOP_RING: 243262306a36Sopenharmony_ci snprintf(str, size, 243362306a36Sopenharmony_ci "%s: slot %d sp %d ep %d flags %c", 243462306a36Sopenharmony_ci xhci_trb_type_string(type), 243562306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 243662306a36Sopenharmony_ci TRB_TO_SUSPEND_PORT(field3), 243762306a36Sopenharmony_ci /* Macro decrements 1, maybe it shouldn't?!? */ 243862306a36Sopenharmony_ci TRB_TO_EP_INDEX(field3) + 1, 243962306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 244062306a36Sopenharmony_ci break; 244162306a36Sopenharmony_ci case TRB_SET_DEQ: 244262306a36Sopenharmony_ci snprintf(str, size, 244362306a36Sopenharmony_ci "%s: deq %08x%08x stream %d slot %d ep %d flags %c", 244462306a36Sopenharmony_ci xhci_trb_type_string(type), 244562306a36Sopenharmony_ci field1, field0, 244662306a36Sopenharmony_ci TRB_TO_STREAM_ID(field2), 244762306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 244862306a36Sopenharmony_ci /* Macro decrements 1, maybe it shouldn't?!? */ 244962306a36Sopenharmony_ci TRB_TO_EP_INDEX(field3) + 1, 245062306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 245162306a36Sopenharmony_ci break; 245262306a36Sopenharmony_ci case TRB_RESET_DEV: 245362306a36Sopenharmony_ci snprintf(str, size, 245462306a36Sopenharmony_ci "%s: slot %d flags %c", 245562306a36Sopenharmony_ci xhci_trb_type_string(type), 245662306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 245762306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 245862306a36Sopenharmony_ci break; 245962306a36Sopenharmony_ci case TRB_FORCE_EVENT: 246062306a36Sopenharmony_ci snprintf(str, size, 246162306a36Sopenharmony_ci "%s: event %08x%08x vf intr %d vf id %d flags %c", 246262306a36Sopenharmony_ci xhci_trb_type_string(type), 246362306a36Sopenharmony_ci field1, field0, 246462306a36Sopenharmony_ci TRB_TO_VF_INTR_TARGET(field2), 246562306a36Sopenharmony_ci TRB_TO_VF_ID(field3), 246662306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 246762306a36Sopenharmony_ci break; 246862306a36Sopenharmony_ci case TRB_SET_LT: 246962306a36Sopenharmony_ci snprintf(str, size, 247062306a36Sopenharmony_ci "%s: belt %d flags %c", 247162306a36Sopenharmony_ci xhci_trb_type_string(type), 247262306a36Sopenharmony_ci TRB_TO_BELT(field3), 247362306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 247462306a36Sopenharmony_ci break; 247562306a36Sopenharmony_ci case TRB_GET_BW: 247662306a36Sopenharmony_ci snprintf(str, size, 247762306a36Sopenharmony_ci "%s: ctx %08x%08x slot %d speed %d flags %c", 247862306a36Sopenharmony_ci xhci_trb_type_string(type), 247962306a36Sopenharmony_ci field1, field0, 248062306a36Sopenharmony_ci TRB_TO_SLOT_ID(field3), 248162306a36Sopenharmony_ci TRB_TO_DEV_SPEED(field3), 248262306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 248362306a36Sopenharmony_ci break; 248462306a36Sopenharmony_ci case TRB_FORCE_HEADER: 248562306a36Sopenharmony_ci snprintf(str, size, 248662306a36Sopenharmony_ci "%s: info %08x%08x%08x pkt type %d roothub port %d flags %c", 248762306a36Sopenharmony_ci xhci_trb_type_string(type), 248862306a36Sopenharmony_ci field2, field1, field0 & 0xffffffe0, 248962306a36Sopenharmony_ci TRB_TO_PACKET_TYPE(field0), 249062306a36Sopenharmony_ci TRB_TO_ROOTHUB_PORT(field3), 249162306a36Sopenharmony_ci field3 & TRB_CYCLE ? 'C' : 'c'); 249262306a36Sopenharmony_ci break; 249362306a36Sopenharmony_ci default: 249462306a36Sopenharmony_ci snprintf(str, size, 249562306a36Sopenharmony_ci "type '%s' -> raw %08x %08x %08x %08x", 249662306a36Sopenharmony_ci xhci_trb_type_string(type), 249762306a36Sopenharmony_ci field0, field1, field2, field3); 249862306a36Sopenharmony_ci } 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci return str; 250162306a36Sopenharmony_ci} 250262306a36Sopenharmony_ci 250362306a36Sopenharmony_cistatic inline const char *xhci_decode_ctrl_ctx(char *str, 250462306a36Sopenharmony_ci unsigned long drop, unsigned long add) 250562306a36Sopenharmony_ci{ 250662306a36Sopenharmony_ci unsigned int bit; 250762306a36Sopenharmony_ci int ret = 0; 250862306a36Sopenharmony_ci 250962306a36Sopenharmony_ci str[0] = '\0'; 251062306a36Sopenharmony_ci 251162306a36Sopenharmony_ci if (drop) { 251262306a36Sopenharmony_ci ret = sprintf(str, "Drop:"); 251362306a36Sopenharmony_ci for_each_set_bit(bit, &drop, 32) 251462306a36Sopenharmony_ci ret += sprintf(str + ret, " %d%s", 251562306a36Sopenharmony_ci bit / 2, 251662306a36Sopenharmony_ci bit % 2 ? "in":"out"); 251762306a36Sopenharmony_ci ret += sprintf(str + ret, ", "); 251862306a36Sopenharmony_ci } 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci if (add) { 252162306a36Sopenharmony_ci ret += sprintf(str + ret, "Add:%s%s", 252262306a36Sopenharmony_ci (add & SLOT_FLAG) ? " slot":"", 252362306a36Sopenharmony_ci (add & EP0_FLAG) ? " ep0":""); 252462306a36Sopenharmony_ci add &= ~(SLOT_FLAG | EP0_FLAG); 252562306a36Sopenharmony_ci for_each_set_bit(bit, &add, 32) 252662306a36Sopenharmony_ci ret += sprintf(str + ret, " %d%s", 252762306a36Sopenharmony_ci bit / 2, 252862306a36Sopenharmony_ci bit % 2 ? "in":"out"); 252962306a36Sopenharmony_ci } 253062306a36Sopenharmony_ci return str; 253162306a36Sopenharmony_ci} 253262306a36Sopenharmony_ci 253362306a36Sopenharmony_cistatic inline const char *xhci_decode_slot_context(char *str, 253462306a36Sopenharmony_ci u32 info, u32 info2, u32 tt_info, u32 state) 253562306a36Sopenharmony_ci{ 253662306a36Sopenharmony_ci u32 speed; 253762306a36Sopenharmony_ci u32 hub; 253862306a36Sopenharmony_ci u32 mtt; 253962306a36Sopenharmony_ci int ret = 0; 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci speed = info & DEV_SPEED; 254262306a36Sopenharmony_ci hub = info & DEV_HUB; 254362306a36Sopenharmony_ci mtt = info & DEV_MTT; 254462306a36Sopenharmony_ci 254562306a36Sopenharmony_ci ret = sprintf(str, "RS %05x %s%s%s Ctx Entries %d MEL %d us Port# %d/%d", 254662306a36Sopenharmony_ci info & ROUTE_STRING_MASK, 254762306a36Sopenharmony_ci ({ char *s; 254862306a36Sopenharmony_ci switch (speed) { 254962306a36Sopenharmony_ci case SLOT_SPEED_FS: 255062306a36Sopenharmony_ci s = "full-speed"; 255162306a36Sopenharmony_ci break; 255262306a36Sopenharmony_ci case SLOT_SPEED_LS: 255362306a36Sopenharmony_ci s = "low-speed"; 255462306a36Sopenharmony_ci break; 255562306a36Sopenharmony_ci case SLOT_SPEED_HS: 255662306a36Sopenharmony_ci s = "high-speed"; 255762306a36Sopenharmony_ci break; 255862306a36Sopenharmony_ci case SLOT_SPEED_SS: 255962306a36Sopenharmony_ci s = "super-speed"; 256062306a36Sopenharmony_ci break; 256162306a36Sopenharmony_ci case SLOT_SPEED_SSP: 256262306a36Sopenharmony_ci s = "super-speed plus"; 256362306a36Sopenharmony_ci break; 256462306a36Sopenharmony_ci default: 256562306a36Sopenharmony_ci s = "UNKNOWN speed"; 256662306a36Sopenharmony_ci } s; }), 256762306a36Sopenharmony_ci mtt ? " multi-TT" : "", 256862306a36Sopenharmony_ci hub ? " Hub" : "", 256962306a36Sopenharmony_ci (info & LAST_CTX_MASK) >> 27, 257062306a36Sopenharmony_ci info2 & MAX_EXIT, 257162306a36Sopenharmony_ci DEVINFO_TO_ROOT_HUB_PORT(info2), 257262306a36Sopenharmony_ci DEVINFO_TO_MAX_PORTS(info2)); 257362306a36Sopenharmony_ci 257462306a36Sopenharmony_ci ret += sprintf(str + ret, " [TT Slot %d Port# %d TTT %d Intr %d] Addr %d State %s", 257562306a36Sopenharmony_ci tt_info & TT_SLOT, (tt_info & TT_PORT) >> 8, 257662306a36Sopenharmony_ci GET_TT_THINK_TIME(tt_info), GET_INTR_TARGET(tt_info), 257762306a36Sopenharmony_ci state & DEV_ADDR_MASK, 257862306a36Sopenharmony_ci xhci_slot_state_string(GET_SLOT_STATE(state))); 257962306a36Sopenharmony_ci 258062306a36Sopenharmony_ci return str; 258162306a36Sopenharmony_ci} 258262306a36Sopenharmony_ci 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_cistatic inline const char *xhci_portsc_link_state_string(u32 portsc) 258562306a36Sopenharmony_ci{ 258662306a36Sopenharmony_ci switch (portsc & PORT_PLS_MASK) { 258762306a36Sopenharmony_ci case XDEV_U0: 258862306a36Sopenharmony_ci return "U0"; 258962306a36Sopenharmony_ci case XDEV_U1: 259062306a36Sopenharmony_ci return "U1"; 259162306a36Sopenharmony_ci case XDEV_U2: 259262306a36Sopenharmony_ci return "U2"; 259362306a36Sopenharmony_ci case XDEV_U3: 259462306a36Sopenharmony_ci return "U3"; 259562306a36Sopenharmony_ci case XDEV_DISABLED: 259662306a36Sopenharmony_ci return "Disabled"; 259762306a36Sopenharmony_ci case XDEV_RXDETECT: 259862306a36Sopenharmony_ci return "RxDetect"; 259962306a36Sopenharmony_ci case XDEV_INACTIVE: 260062306a36Sopenharmony_ci return "Inactive"; 260162306a36Sopenharmony_ci case XDEV_POLLING: 260262306a36Sopenharmony_ci return "Polling"; 260362306a36Sopenharmony_ci case XDEV_RECOVERY: 260462306a36Sopenharmony_ci return "Recovery"; 260562306a36Sopenharmony_ci case XDEV_HOT_RESET: 260662306a36Sopenharmony_ci return "Hot Reset"; 260762306a36Sopenharmony_ci case XDEV_COMP_MODE: 260862306a36Sopenharmony_ci return "Compliance mode"; 260962306a36Sopenharmony_ci case XDEV_TEST_MODE: 261062306a36Sopenharmony_ci return "Test mode"; 261162306a36Sopenharmony_ci case XDEV_RESUME: 261262306a36Sopenharmony_ci return "Resume"; 261362306a36Sopenharmony_ci default: 261462306a36Sopenharmony_ci break; 261562306a36Sopenharmony_ci } 261662306a36Sopenharmony_ci return "Unknown"; 261762306a36Sopenharmony_ci} 261862306a36Sopenharmony_ci 261962306a36Sopenharmony_cistatic inline const char *xhci_decode_portsc(char *str, u32 portsc) 262062306a36Sopenharmony_ci{ 262162306a36Sopenharmony_ci int ret; 262262306a36Sopenharmony_ci 262362306a36Sopenharmony_ci ret = sprintf(str, "%s %s %s Link:%s PortSpeed:%d ", 262462306a36Sopenharmony_ci portsc & PORT_POWER ? "Powered" : "Powered-off", 262562306a36Sopenharmony_ci portsc & PORT_CONNECT ? "Connected" : "Not-connected", 262662306a36Sopenharmony_ci portsc & PORT_PE ? "Enabled" : "Disabled", 262762306a36Sopenharmony_ci xhci_portsc_link_state_string(portsc), 262862306a36Sopenharmony_ci DEV_PORT_SPEED(portsc)); 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci if (portsc & PORT_OC) 263162306a36Sopenharmony_ci ret += sprintf(str + ret, "OverCurrent "); 263262306a36Sopenharmony_ci if (portsc & PORT_RESET) 263362306a36Sopenharmony_ci ret += sprintf(str + ret, "In-Reset "); 263462306a36Sopenharmony_ci 263562306a36Sopenharmony_ci ret += sprintf(str + ret, "Change: "); 263662306a36Sopenharmony_ci if (portsc & PORT_CSC) 263762306a36Sopenharmony_ci ret += sprintf(str + ret, "CSC "); 263862306a36Sopenharmony_ci if (portsc & PORT_PEC) 263962306a36Sopenharmony_ci ret += sprintf(str + ret, "PEC "); 264062306a36Sopenharmony_ci if (portsc & PORT_WRC) 264162306a36Sopenharmony_ci ret += sprintf(str + ret, "WRC "); 264262306a36Sopenharmony_ci if (portsc & PORT_OCC) 264362306a36Sopenharmony_ci ret += sprintf(str + ret, "OCC "); 264462306a36Sopenharmony_ci if (portsc & PORT_RC) 264562306a36Sopenharmony_ci ret += sprintf(str + ret, "PRC "); 264662306a36Sopenharmony_ci if (portsc & PORT_PLC) 264762306a36Sopenharmony_ci ret += sprintf(str + ret, "PLC "); 264862306a36Sopenharmony_ci if (portsc & PORT_CEC) 264962306a36Sopenharmony_ci ret += sprintf(str + ret, "CEC "); 265062306a36Sopenharmony_ci if (portsc & PORT_CAS) 265162306a36Sopenharmony_ci ret += sprintf(str + ret, "CAS "); 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci ret += sprintf(str + ret, "Wake: "); 265462306a36Sopenharmony_ci if (portsc & PORT_WKCONN_E) 265562306a36Sopenharmony_ci ret += sprintf(str + ret, "WCE "); 265662306a36Sopenharmony_ci if (portsc & PORT_WKDISC_E) 265762306a36Sopenharmony_ci ret += sprintf(str + ret, "WDE "); 265862306a36Sopenharmony_ci if (portsc & PORT_WKOC_E) 265962306a36Sopenharmony_ci ret += sprintf(str + ret, "WOE "); 266062306a36Sopenharmony_ci 266162306a36Sopenharmony_ci return str; 266262306a36Sopenharmony_ci} 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_cistatic inline const char *xhci_decode_usbsts(char *str, u32 usbsts) 266562306a36Sopenharmony_ci{ 266662306a36Sopenharmony_ci int ret = 0; 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci ret = sprintf(str, " 0x%08x", usbsts); 266962306a36Sopenharmony_ci 267062306a36Sopenharmony_ci if (usbsts == ~(u32)0) 267162306a36Sopenharmony_ci return str; 267262306a36Sopenharmony_ci 267362306a36Sopenharmony_ci if (usbsts & STS_HALT) 267462306a36Sopenharmony_ci ret += sprintf(str + ret, " HCHalted"); 267562306a36Sopenharmony_ci if (usbsts & STS_FATAL) 267662306a36Sopenharmony_ci ret += sprintf(str + ret, " HSE"); 267762306a36Sopenharmony_ci if (usbsts & STS_EINT) 267862306a36Sopenharmony_ci ret += sprintf(str + ret, " EINT"); 267962306a36Sopenharmony_ci if (usbsts & STS_PORT) 268062306a36Sopenharmony_ci ret += sprintf(str + ret, " PCD"); 268162306a36Sopenharmony_ci if (usbsts & STS_SAVE) 268262306a36Sopenharmony_ci ret += sprintf(str + ret, " SSS"); 268362306a36Sopenharmony_ci if (usbsts & STS_RESTORE) 268462306a36Sopenharmony_ci ret += sprintf(str + ret, " RSS"); 268562306a36Sopenharmony_ci if (usbsts & STS_SRE) 268662306a36Sopenharmony_ci ret += sprintf(str + ret, " SRE"); 268762306a36Sopenharmony_ci if (usbsts & STS_CNR) 268862306a36Sopenharmony_ci ret += sprintf(str + ret, " CNR"); 268962306a36Sopenharmony_ci if (usbsts & STS_HCE) 269062306a36Sopenharmony_ci ret += sprintf(str + ret, " HCE"); 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci return str; 269362306a36Sopenharmony_ci} 269462306a36Sopenharmony_ci 269562306a36Sopenharmony_cistatic inline const char *xhci_decode_doorbell(char *str, u32 slot, u32 doorbell) 269662306a36Sopenharmony_ci{ 269762306a36Sopenharmony_ci u8 ep; 269862306a36Sopenharmony_ci u16 stream; 269962306a36Sopenharmony_ci int ret; 270062306a36Sopenharmony_ci 270162306a36Sopenharmony_ci ep = (doorbell & 0xff); 270262306a36Sopenharmony_ci stream = doorbell >> 16; 270362306a36Sopenharmony_ci 270462306a36Sopenharmony_ci if (slot == 0) { 270562306a36Sopenharmony_ci sprintf(str, "Command Ring %d", doorbell); 270662306a36Sopenharmony_ci return str; 270762306a36Sopenharmony_ci } 270862306a36Sopenharmony_ci ret = sprintf(str, "Slot %d ", slot); 270962306a36Sopenharmony_ci if (ep > 0 && ep < 32) 271062306a36Sopenharmony_ci ret = sprintf(str + ret, "ep%d%s", 271162306a36Sopenharmony_ci ep / 2, 271262306a36Sopenharmony_ci ep % 2 ? "in" : "out"); 271362306a36Sopenharmony_ci else if (ep == 0 || ep < 248) 271462306a36Sopenharmony_ci ret = sprintf(str + ret, "Reserved %d", ep); 271562306a36Sopenharmony_ci else 271662306a36Sopenharmony_ci ret = sprintf(str + ret, "Vendor Defined %d", ep); 271762306a36Sopenharmony_ci if (stream) 271862306a36Sopenharmony_ci ret = sprintf(str + ret, " Stream %d", stream); 271962306a36Sopenharmony_ci 272062306a36Sopenharmony_ci return str; 272162306a36Sopenharmony_ci} 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_cistatic inline const char *xhci_ep_state_string(u8 state) 272462306a36Sopenharmony_ci{ 272562306a36Sopenharmony_ci switch (state) { 272662306a36Sopenharmony_ci case EP_STATE_DISABLED: 272762306a36Sopenharmony_ci return "disabled"; 272862306a36Sopenharmony_ci case EP_STATE_RUNNING: 272962306a36Sopenharmony_ci return "running"; 273062306a36Sopenharmony_ci case EP_STATE_HALTED: 273162306a36Sopenharmony_ci return "halted"; 273262306a36Sopenharmony_ci case EP_STATE_STOPPED: 273362306a36Sopenharmony_ci return "stopped"; 273462306a36Sopenharmony_ci case EP_STATE_ERROR: 273562306a36Sopenharmony_ci return "error"; 273662306a36Sopenharmony_ci default: 273762306a36Sopenharmony_ci return "INVALID"; 273862306a36Sopenharmony_ci } 273962306a36Sopenharmony_ci} 274062306a36Sopenharmony_ci 274162306a36Sopenharmony_cistatic inline const char *xhci_ep_type_string(u8 type) 274262306a36Sopenharmony_ci{ 274362306a36Sopenharmony_ci switch (type) { 274462306a36Sopenharmony_ci case ISOC_OUT_EP: 274562306a36Sopenharmony_ci return "Isoc OUT"; 274662306a36Sopenharmony_ci case BULK_OUT_EP: 274762306a36Sopenharmony_ci return "Bulk OUT"; 274862306a36Sopenharmony_ci case INT_OUT_EP: 274962306a36Sopenharmony_ci return "Int OUT"; 275062306a36Sopenharmony_ci case CTRL_EP: 275162306a36Sopenharmony_ci return "Ctrl"; 275262306a36Sopenharmony_ci case ISOC_IN_EP: 275362306a36Sopenharmony_ci return "Isoc IN"; 275462306a36Sopenharmony_ci case BULK_IN_EP: 275562306a36Sopenharmony_ci return "Bulk IN"; 275662306a36Sopenharmony_ci case INT_IN_EP: 275762306a36Sopenharmony_ci return "Int IN"; 275862306a36Sopenharmony_ci default: 275962306a36Sopenharmony_ci return "INVALID"; 276062306a36Sopenharmony_ci } 276162306a36Sopenharmony_ci} 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_cistatic inline const char *xhci_decode_ep_context(char *str, u32 info, 276462306a36Sopenharmony_ci u32 info2, u64 deq, u32 tx_info) 276562306a36Sopenharmony_ci{ 276662306a36Sopenharmony_ci int ret; 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci u32 esit; 276962306a36Sopenharmony_ci u16 maxp; 277062306a36Sopenharmony_ci u16 avg; 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci u8 max_pstr; 277362306a36Sopenharmony_ci u8 ep_state; 277462306a36Sopenharmony_ci u8 interval; 277562306a36Sopenharmony_ci u8 ep_type; 277662306a36Sopenharmony_ci u8 burst; 277762306a36Sopenharmony_ci u8 cerr; 277862306a36Sopenharmony_ci u8 mult; 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_ci bool lsa; 278162306a36Sopenharmony_ci bool hid; 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | 278462306a36Sopenharmony_ci CTX_TO_MAX_ESIT_PAYLOAD(tx_info); 278562306a36Sopenharmony_ci 278662306a36Sopenharmony_ci ep_state = info & EP_STATE_MASK; 278762306a36Sopenharmony_ci max_pstr = CTX_TO_EP_MAXPSTREAMS(info); 278862306a36Sopenharmony_ci interval = CTX_TO_EP_INTERVAL(info); 278962306a36Sopenharmony_ci mult = CTX_TO_EP_MULT(info) + 1; 279062306a36Sopenharmony_ci lsa = !!(info & EP_HAS_LSA); 279162306a36Sopenharmony_ci 279262306a36Sopenharmony_ci cerr = (info2 & (3 << 1)) >> 1; 279362306a36Sopenharmony_ci ep_type = CTX_TO_EP_TYPE(info2); 279462306a36Sopenharmony_ci hid = !!(info2 & (1 << 7)); 279562306a36Sopenharmony_ci burst = CTX_TO_MAX_BURST(info2); 279662306a36Sopenharmony_ci maxp = MAX_PACKET_DECODED(info2); 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci avg = EP_AVG_TRB_LENGTH(tx_info); 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_ci ret = sprintf(str, "State %s mult %d max P. Streams %d %s", 280162306a36Sopenharmony_ci xhci_ep_state_string(ep_state), mult, 280262306a36Sopenharmony_ci max_pstr, lsa ? "LSA " : ""); 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci ret += sprintf(str + ret, "interval %d us max ESIT payload %d CErr %d ", 280562306a36Sopenharmony_ci (1 << interval) * 125, esit, cerr); 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_ci ret += sprintf(str + ret, "Type %s %sburst %d maxp %d deq %016llx ", 280862306a36Sopenharmony_ci xhci_ep_type_string(ep_type), hid ? "HID" : "", 280962306a36Sopenharmony_ci burst, maxp, deq); 281062306a36Sopenharmony_ci 281162306a36Sopenharmony_ci ret += sprintf(str + ret, "avg trb len %d", avg); 281262306a36Sopenharmony_ci 281362306a36Sopenharmony_ci return str; 281462306a36Sopenharmony_ci} 281562306a36Sopenharmony_ci 281662306a36Sopenharmony_ci#endif /* __LINUX_XHCI_HCD_H */ 2817