diff options
Diffstat (limited to 'sys/dev/thunderbolt/nhi_reg.h')
-rw-r--r-- | sys/dev/thunderbolt/nhi_reg.h | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/sys/dev/thunderbolt/nhi_reg.h b/sys/dev/thunderbolt/nhi_reg.h new file mode 100644 index 000000000000..6e71f4c9646b --- /dev/null +++ b/sys/dev/thunderbolt/nhi_reg.h @@ -0,0 +1,332 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2022 Scott Long + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Thunderbolt 3 register definitions + */ + +/* $FreeBSD$ */ + +#ifndef _NHI_REG_H +#define _NHI_REG_H + +/* Some common definitions */ +#define TBT_SEC_NONE 0x00 +#define TBT_SEC_USER 0x01 +#define TBT_SEC_SECURE 0x02 +#define TBT_SEC_DP 0x03 + +#define GENMASK(h, l) (((~0U) >> (31 - (h))) ^ ((~0U) >> (31 - (l)) >> 1)) + +/* PCI Vendor and Device ID's */ +#define VENDOR_INTEL 0x8086 +#define DEVICE_AR_2C_NHI 0x1575 +#define DEVICE_AR_DP_B_NHI 0x1577 +#define DEVICE_AR_DP_C_NHI 0x15d2 +#define DEVICE_AR_LP_NHI 0x15bf +#define DEVICE_ICL_NHI_0 0x8a17 +#define DEVICE_ICL_NHI_1 0x8a0d + +#define VENDOR_AMD 0x1022 +#define DEVICE_PINK_SARDINE_0 0x1668 +#define DEVICE_PINK_SARDINE_1 0x1669 + +/* * * MMIO Registers + * * Ring buffer registers + * + * 32 transmit and receive rings are available, with Ring 0 being the most + * important one. The ring descriptors are 16 bytes each, and each set of + * TX and RX descriptors are packed together. There are only definitions + * for the Ring 0 addresses, others can be directly computed. + */ +#define NHI_TX_RING_ADDR_LO 0x00000 +#define NHI_TX_RING_ADDR_HI 0x00004 +#define NHI_TX_RING_PICI 0x00008 +#define TX_RING_CI_MASK GENMASK(15, 0) +#define TX_RING_PI_SHIFT 16 +#define NHI_TX_RING_SIZE 0x0000c + +#define NHI_RX_RING_ADDR_LO 0x08000 +#define NHI_RX_RING_ADDR_HI 0x08004 +#define NHI_RX_RING_PICI 0x08008 +#define RX_RING_CI_MASK GENMASK(15, 0) +#define RX_RING_PI_SHIFT 16 +#define NHI_RX_RING_SIZE 0x0800c +#define RX_RING_BUF_SIZE_SHIFT 16 + +/* + * One 32-bit status register encodes one status bit per ring indicates that + * the watermark from the control descriptor has been reached. + */ +#define NHI_RX_RING_STATUS 0x19400 + +/* + * TX and RX Tables. These are 32 byte control fields for each ring. + * Only 8 bytes are controllable by the host software, the rest are a + * shadow copy by the controller of the current packet that's being + * processed. + */ +#define NHI_TX_RING_TABLE_BASE0 0x19800 +#define TX_TABLE_INTERVAL_MASK GENMASK(23,0) /* Isoch interval 256ns */ +#define TX_TABLE_ITE (1 << 27) /* Isoch tx enable */ +#define TX_TABLE_E2E (1 << 28) /* End-to-end flow control */ +#define TX_TABLE_NS (1 << 29) /* PCIe No Snoop */ +#define TX_TABLE_RAW (1 << 30) /* Raw (1)/frame(0) mode */ +#define TX_TABLE_VALID (1 << 31) /* Table entry is valid */ +#define NHI_TX_RING_TABLE_TIMESTAMP 0x19804 + +#define NHI_RX_RING_TABLE_BASE0 0x29800 +#define RX_TABLE_TX_E2E_HOPID_SHIFT (1 << 12) +#define RX_TABLE_E2E (1 << 28) /* End-to-end flow control */ +#define RX_TABLE_NS (1 << 29) /* PCIe No Snoop */ +#define RX_TABLE_RAW (1 << 30) /* Raw (1)/frame(0) mode */ +#define RX_TABLE_VALID (1 << 31) /* Table entry is valid */ +#define NHI_RX_RING_TABLE_BASE1 0x29804 +#define RX_TABLE_EOF_MASK (1 << 0) +#define RX_TABLE_SOF_MASK (1 << 16) + +/* * Interrupt Control/Status Registers + * Interrupt Status Register (ISR) + * Interrupt status for RX, TX, and Nearly Empty events, one bit per + * MSI-X vector. Clear on read. + * Only 12 bits per operation, instead of 16? I guess it relates to the + * number paths, advertised in the HOST_CAPS register, which is wired to + * 0x0c for Alpine Ridge. + */ +#define NHI_ISR0 0x37800 +#define ISR0_TX_DESC_SHIFT 0 +#define ISR0_RX_DESC_SHIFT 12 +#define ISR0_RX_EMPTY_SHIFT 24 +#define NHI_ISR1 0x37804 +#define ISR1_RX_EMPTY_SHIFT 0 + +/* * Interrupt Status Clear, corresponds to ISR0/ISR1. Write Only */ +#define NHI_ISC0 0x37808 +#define NHI_ISC1 0x3780c + +/* * Interrupt Status Set, corresponds to ISR0/ISR1. Write Only */ +#define NHI_ISS0 0x37810 +#define NHI_ISS1 0x37814 + +/* * Interrupt Mask, corresponds to ISR0/ISR1. Read-Write */ +#define NHI_IMR0 0x38200 +#define NHI_IMR1 0x38204 +#define IMR_TX_OFFSET 0 +#define IMR_RX_OFFSET 12 +#define IMR_NE_OFFSET 24 + +/* * Interrupt Mask Clear, corresponds to ISR0/ISR1. Write-only */ +#define NHI_IMC0 0x38208 +#define NHI_IMC1 0x3820c + +/* * Interrupt Mask Set, corresponds to ISR0/ISR1. Write-only */ +#define NHI_IMS0 0x38210 +#define NHI_IMS1 0x38214 + +/* + * Interrupt Throttle Rate. One 32 bit register per interrupt, + * 16 registers for the 16 MSI-X interrupts. Interval is in 256ns + * increments. + */ +#define NHI_ITR0 0x38c00 +#define ITR_INTERVAL_SHIFT 0 +#define ITR_COUNTER_SHIFT 16 + +/* + * Interrupt Vector Allocation. + * There are 12 4-bit descriptors for TX, 12 4-bit descriptors for RX, + * and 12 4-bit descriptors for Nearly Empty. Each descriptor holds + * the numerical value of the MSI-X vector that will receive the + * corresponding interrupt. + * Bits 0-31 of IVR0 and 0-15 of IVR1 are for TX + * Bits 16-31 of IVR1 and 0-31 of IVR2 are for RX + * Bits 0-31 of IVR3 and 0-15 of IVR4 are for Nearly Empty + */ +#define NHI_IVR0 0x38c40 +#define NHI_IVR1 0x38c44 +#define NHI_IVR2 0x38c48 +#define NHI_IVR3 0x38c4c +#define NHI_IVR4 0x38c50 +#define IVR_TX_OFFSET 0 +#define IVR_RX_OFFSET 12 +#define IVR_NE_OFFSET 24 + +/* Native Host Interface Control registers */ +#define NHI_HOST_CAPS 0x39640 +#define GET_HOST_CAPS_PATHS(val) ((val) & 0x3f) + +/* + * This definition comes from the Linux driver. In the USB4 spec, this + * register is named Host Interface Control, and the Interrupt Autoclear bit + * is at bit17, not bit2. The Linux driver doesn't seem to acknowledge this. + */ +#define NHI_DMA_MISC 0x39864 +#define DMA_MISC_INT_AUTOCLEAR (1 << 2) + +/* Thunderbolt firmware mailbox registers */ +#define TBT_INMAILDATA 0x39900 + +#define TBT_INMAILCMD 0x39904 +#define INMAILCMD_CMD_MASK 0xff +#define INMAILCMD_SAVE_CONNECTED 0x05 +#define INMAILCMD_DISCONNECT_PCIE 0x06 +#define INMAILCMD_DRIVER_UNLOAD_DISCONNECT 0x07 +#define INMAILCMD_DISCONNECT_PORTA 0x10 +#define INMAILCMD_DISCONNECT_PORTB 0x11 +#define INMAILCMD_SETMODE_CERT_TB_1ST_DEPTH 0x20 +#define INMAILCMD_SETMODE_ANY_TB_1ST_DEPTH 0x21 +#define INMAILCMD_SETMODE_CERT_TB_ANY_DEPTH 0x22 +#define INMAILCMD_SETMODE_ANY_TB_ANY_DEPTH 0x23 +#define INMAILCMD_CIO_RESET 0xf0 +#define INMAILCMD_ERROR (1 << 30) +#define INMAILCMD_OPREQ (1 << 31) + +#define TBT_OUTMAILCMD 0x3990c +#define OUTMAILCMD_STATUS_BUSY (1 << 12) +#define OUTMAILCMD_OPMODE_MASK 0xf00 +#define OUTMAILCMD_OPMODE_SAFE 0x000 +#define OUTMAILCMD_OPMODE_AUTH 0x100 +#define OUTMAILCMD_OPMODE_ENDPOINT 0x200 +#define OUTMAILCMD_OPMODE_CM_FULL 0x300 + +#define TBT_FW_STATUS 0x39944 +#define FWSTATUS_ENABLE (1 << 0) +#define FWSTATUS_INVERT (1 << 1) +#define FWSTATUS_START (1 << 2) +#define FWSTATUS_CIO_RESET (1 << 30) +#define FWSTATUS_CM_READY (1 << 31) + +/* + * Link Controller (LC) registers. These are in the Vendor Specific + * Extended Capability registers in PCICFG. + */ +#define AR_LC_MBOX_OUT 0x4c +#define ICL_LC_MBOX_OUT 0xf0 +#define LC_MBOXOUT_VALID (1 << 0) +#define LC_MBOXOUT_CMD_SHIFT 1 +#define LC_MBOXOUT_CMD_MASK (0x7f << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_CMD_GO2SX (0x02 << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_CMD_GO2SX_NOWAKE (0x03 << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_CMD_SXEXIT_TBT (0x04 << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_CMD_SXEXIT_NOTBT (0x05 << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_CMD_OS_UP (0x06 << LC_MBOXOUT_CMD_SHIFT) +#define LC_MBOXOUT_DATA_SHIFT 8 +#define SET_LC_MBOXOUT_DATA(val) ((val) << LC_MBOXOUT_DATA_SHIFT) + +#define AR_LC_MBOX_IN 0x48 +#define ICL_LC_MBOX_IN 0xec +#define LC_MBOXIN_DONE (1 << 0) +#define LC_MBOXIN_CMD_SHIFT 1 +#define LC_MBOXIN_CMD_MASK (0x7f << LC_MBOXIN_CMD_SHIFT) +#define LC_MBOXIN_DATA_SHIFT 8 +#define GET_LC_MBOXIN_DATA(val) ((val) >> LC_MBOXIN_DATA_SHIFT) + +/* Other Vendor Specific registers */ +#define AR_VSCAP_1C 0x1c +#define AR_VSCAP_B0 0xb0 + +#define ICL_VSCAP_9 0xc8 +#define ICL_VSCAP9_FWREADY (1 << 31) +#define ICL_VSCAP_10 0xcc +#define ICL_VSCAP_11 0xd0 +#define ICL_VSCAP_22 0xfc +#define ICL_VSCAP22_FORCEPWR (1 << 1) + +/* * Data structures + * Transmit buffer descriptor, 12.3.1. Must be aligned on a 4byte boundary. + */ +struct nhi_tx_buffer_desc { + uint32_t addr_lo; + uint32_t addr_hi; + uint16_t eof_len; +#define TX_BUFFER_DESC_LEN_MASK 0xfff +#define TX_BUFFER_DESC_EOF_SHIFT 12 + uint8_t flags_sof; +#define TX_BUFFER_DESC_SOF_MASK 0xf +#define TX_BUFFER_DESC_IDE (1 << 4) /* Isoch DMA enable */ +#define TX_BUFFER_DESC_DONE (1 << 5) /* Descriptor Done */ +#define TX_BUFFER_DESC_RS (1 << 6) /* Request Status/Done */ +#define TX_BUFFER_DESC_IE (1 << 7) /* Interrupt Enable */ + uint8_t offset; + uint32_t payload_time; +} __packed; + +/* + * Receive buffer descriptor, 12.4.1. 4 byte aligned. This goes into + * the descriptor ring, but changes into the _post form when the + * controller uses it. + */ +struct nhi_rx_buffer_desc { + uint32_t addr_lo; + uint32_t addr_hi; + uint16_t reserved0; + uint8_t flags; +#define RX_BUFFER_DESC_RS (1 << 6) /* Request Status/Done */ +#define RX_BUFFER_DESC_IE (1 << 7) /* Interrupt Enable */ + uint8_t offset; + uint32_t reserved1; +} __packed; + +/* + * Receive buffer descriptor, after the controller fills it in + */ +struct nhi_rx_post_desc { + uint32_t addr_lo; + uint32_t addr_hi; + uint16_t eof_len; +#define RX_BUFFER_DESC_LEN_MASK 0xfff +#define RX_BUFFER_DESC_EOF_SHIFT 12 + uint8_t flags_sof; +#define RX_BUFFER_DESC_SOF_MASK 0xf +#define RX_BUFFER_DESC_CRC_ERROR (1 << 4) /* CRC error (frame mode) */ +#define RX_BUFFER_DESC_DONE (1 << 5) /* Descriptor Done */ +#define RX_BUFFER_DESC_OVERRUN (1 << 6) /* Buffer overrun */ +#define RX_BUFFER_DESC_IE (1 << 7) /* Interrupt Enable */ + uint8_t offset; + uint32_t payload_time; +} __packed; + +union nhi_ring_desc { + struct nhi_tx_buffer_desc tx; + struct nhi_rx_buffer_desc rx; + struct nhi_rx_post_desc rxpost; + uint32_t dword[4]; +}; + +/* Protocol Defined Field (PDF) */ +#define PDF_READ 0x01 +#define PDF_WRITE 0x02 +#define PDF_NOTIFY 0x03 +#define PDF_NOTIFY_ACK 0x04 +#define PDF_HOTPLUG 0x05 +#define PDF_XDOMAIN_REQ 0x06 +#define PDF_XDOMAIN_RESP 0x07 +/* Thunderbolt-only */ +#define PDF_CM_EVENT 0x0a +#define PDF_CM_REQ 0x0b +#define PDF_CM_RESP 0x0c + +#endif /* _NHI_REG_H */ |