aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/thunderbolt/nhi_reg.h
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/thunderbolt/nhi_reg.h')
-rw-r--r--sys/dev/thunderbolt/nhi_reg.h332
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 */