feat(pcie): add PCIe DOE library
This patch adds PCIe DOE library source files.
Change-Id: Ic2ab11afa0438d74c53cb157a63caada7457d77e
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/include/lib/pcie/pcie.h b/include/lib/pcie/pcie.h
new file mode 100644
index 0000000..aa3911f
--- /dev/null
+++ b/include/lib/pcie/pcie.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2024, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef PCIE_H
+#define PCIE_H
+
+#include <cdefs.h>
+#include <stdint.h>
+#include <utils_def.h>
+
+typedef struct {
+ unsigned long ecam_base; /* ECAM base address */
+ unsigned int segment_num; /* Segment number of this ECAM */
+ unsigned int start_bus_num; /* Start bus number for this ECAM space */
+ unsigned int end_bus_num; /* Last bus number */
+} pcie_info_block_t;
+
+typedef struct {
+ unsigned int num_entries; /* Number of entries */
+ pcie_info_block_t block[];
+} pcie_info_table_t;
+
+typedef struct {
+ uint32_t bdf;
+ uint32_t rp_bdf;
+} pcie_device_attr_t;
+
+typedef struct __packed {
+ uint32_t num_entries;
+ pcie_device_attr_t device[]; /* in the format of Segment/Bus/Dev/Func */
+} pcie_device_bdf_table_t;
+
+/* Address initialisation structure */
+typedef struct {
+ /* 64 bit prefetchable memory start address */
+ uint64_t bar64_p_start;
+ uint64_t rp_bar64_value;
+ /* 32 bit non-prefetchable memory start address */
+ uint32_t bar32_np_start;
+ /* 32 bit prefetchable memory start address */
+ uint32_t bar32_p_start;
+ uint32_t rp_bar32_value;
+} pcie_bar_init_t;
+
+#define PCIE_EXTRACT_BDF_SEG(bdf) ((bdf >> 24) & 0xFF)
+#define PCIE_EXTRACT_BDF_BUS(bdf) ((bdf >> 16) & 0xFF)
+#define PCIE_EXTRACT_BDF_DEV(bdf) ((bdf >> 8) & 0xFF)
+#define PCIE_EXTRACT_BDF_FUNC(bdf) (bdf & 0xFF)
+
+/* PCI-compatible region */
+#define PCI_CMP_CFG_SIZE 256
+
+/* PCI Express Extended Configuration Space */
+#define PCIE_CFG_SIZE 4096
+
+#define PCIE_MAX_BUS 256
+#define PCIE_MAX_DEV 32
+#define PCIE_MAX_FUNC 8
+
+#define PCIE_CREATE_BDF(Seg, Bus, Dev, Func) \
+ ((Seg << 24) | (Bus << 16) | (Dev << 8) | Func)
+
+#define PCIE_SUCCESS 0x00000000 /* Operation completed successfully */
+#define PCIE_NO_MAPPING 0x10000001 /* A mapping to a Function does not exist */
+#define PCIE_CAP_NOT_FOUND 0x10000010 /* The specified capability was not found */
+#define PCIE_UNKNOWN_RESPONSE 0xFFFFFFFF /* Function not found or UR response from completer */
+
+/* Allows storage of 2048 valid BDFs */
+#define PCIE_DEVICE_BDF_TABLE_SZ 8192
+
+typedef enum {
+ HEADER = 0,
+ PCIE_CAP = 1,
+ PCIE_ECAP = 2
+} bitfield_reg_type_t;
+
+typedef enum {
+ HW_INIT = 0,
+ READ_ONLY = 1,
+ STICKY_RO = 2,
+ RSVDP_RO = 3,
+ RSVDZ_RO = 4,
+ READ_WRITE = 5,
+ STICKY_RW = 6
+} bitfield_attr_type_t;
+
+/* Class Code Masks */
+#define CC_SUB_MASK 0xFF /* Sub Class */
+#define CC_BASE_MASK 0xFF /* Base Class */
+
+/* Class Code Shifts */
+#define CC_SHIFT 8
+#define CC_SUB_SHIFT 16
+#define CC_BASE_SHIFT 24
+
+void pcie_create_info_table(void);
+pcie_device_bdf_table_t *pcie_get_bdf_table(void);
+uint32_t pcie_find_capability(uint32_t bdf, uint32_t cid_type, uint32_t cid,
+ uint32_t *cid_offset);
+uint32_t pcie_read_cfg(uint32_t bdf, uint32_t offset);
+void pcie_write_cfg(uint32_t bdf, uint32_t offset, uint32_t data);
+
+#endif /* PCIE_H */
diff --git a/include/lib/pcie/pcie_doe.h b/include/lib/pcie/pcie_doe.h
new file mode 100644
index 0000000..4e12afd
--- /dev/null
+++ b/include/lib/pcie/pcie_doe.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2024, Arm Limited or its affiliates. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PCIE_DOE_H
+#define PCIE_DOE_H
+
+/* DOE Extended Capability */
+#define DOE_CAP_ID 0x002E
+
+#define DOE_CAP_REG 0x4
+#define DOE_CTRL_REG 0x8
+#define DOE_STATUS_REG 0xC
+#define DOE_WRITE_DATA_MAILBOX_REG 0x10
+#define DOE_READ_DATA_MAILBOX_REG 0x14
+
+#define DOE_CTRL_ABORT_BIT (1 << 0)
+#define DOE_CTRL_GO_BIT (1 << 31)
+
+#define DOE_STATUS_BUSY_BIT (1 << 0)
+#define DOE_STATUS_ERROR_BIT (1 << 2)
+#define DOE_STATUS_READY_BIT (1 << 31)
+
+/* Time intervals in ms */
+#define PCI_DOE_TIMEOUT 1000
+#define PCI_DOE_POLL_TIME 10
+
+#define PCI_DOE_POLL_LOOP (PCI_DOE_TIMEOUT / PCI_DOE_POLL_TIME)
+
+/* DOE Data Object Header 2 Reserved field [31:18] */
+#define PCI_DOE_RESERVED_SHIFT 18
+#define PCI_DOE_RESERVED_MASK 0xFFFC0000
+
+/* Max data object length is 2^18 DW */
+#define PCI_DOE_MAX_LENGTH (1 << PCI_DOE_RESERVED_SHIFT)
+
+/* SPDM GET_VERSION response DW length */
+#define SPDM_GET_VERS_RESP_LEN \
+ ((sizeof(spdm_version_response_t) + \
+ (sizeof(spdm_version_number_t) * SPDM_MAX_VERSION_COUNT) + \
+ (sizeof(uint32_t) - 1)) << 2)
+
+/* PCI-SIG Vendor ID */
+#define PSI_SIG_VENDOR_ID 1
+
+/* Data Object Protocols */
+#define DOE_DISC_PROTOCOL 0
+#define CMA_SPDM_PROTOCOL 1
+#define SEC_CMA_SPDM_PROTOCOL 2
+
+#define DOE_HEADER(_type) ((_type << 16) | PSI_SIG_VENDOR_ID)
+
+#define DOE_HEADER_0 DOE_HEADER(DOE_DISC_PROTOCOL)
+#define DOE_HEADER_1 DOE_HEADER(CMA_SPDM_PROTOCOL)
+#define DOE_HEADER_2 DOE_HEADER(SEC_CMA_SPDM_PROTOCOL)
+#define DOE_HEADER_LENGTH 2
+
+/*
+ * SPDM VERSION structure:
+ * bit[15:12] major_version
+ * bit[11:8] minor_version
+ * bit[7:4] update_version_number
+ * bit[3:0] alpha
+ */
+#define SPDM_VER_MAJOR_SHIFT 12
+#define SPDM_VER_MAJOR_WIDTH 4
+#define SPDM_VER_MINOR_SHIFT 8
+#define SPDM_VER_MINOR_WIDTH 4
+#define SPDM_VER_UPDATE_SHIFT 4
+#define SPDM_VER_UPDATE_WIDTH 4
+#define SPDM_VER_ALPHA_SHIFT 0
+#define SPDM_VER_ALPHA_WIDTH 4
+
+/* DOE Discovery */
+typedef struct {
+ uint8_t index;
+ uint8_t reserved[3];
+} pcie_doe_disc_req_t;
+
+typedef struct {
+ uint16_t vendor_id;
+ uint8_t data_object_type;
+ uint8_t next_index;
+} pcie_doe_disc_resp_t;
+
+void print_doe_disc(pcie_doe_disc_resp_t *data);
+int pcie_doe_send_req(uint32_t header, uint32_t bdf, uint32_t doe_cap_base,
+ uint32_t *req_addr, uint32_t req_len);
+int pcie_doe_recv_resp(uint32_t bdf, uint32_t doe_cap_base,
+ uint32_t *resp_addr, uint32_t *resp_len);
+
+#endif /* PCIE_DOE_H */
diff --git a/include/lib/pcie/pcie_spec.h b/include/lib/pcie/pcie_spec.h
new file mode 100644
index 0000000..31fd98b
--- /dev/null
+++ b/include/lib/pcie/pcie_spec.h
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2024, Arm Limited or its affiliates. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PCIE_SPEC_H
+#define PCIE_SPEC_H
+
+/* Header Type */
+#define TYPE0_HEADER 0
+#define TYPE1_HEADER 1
+
+/* TYPE 0/1 Cmn Cfg reg offsets */
+#define TYPE01_VIDR 0x0
+#define TYPE01_CR 0x4
+#define TYPE01_RIDR 0x8
+#define TYPE01_CLSR 0xc
+#define TYPE01_BAR 0x10
+#define TYPE01_CPR 0x34
+#define TYPE01_ILR 0x3c
+
+/* TYPE 0/1 Cmn Cfg reg shifts and masks */
+#define TYPE01_VIDR_SHIFT 0
+#define TYPE01_VIDR_MASK 0xffff
+#define TYPE01_DIDR_SHIFT 16
+#define TYPE01_DIDR_MASK 0xffff
+#define TYPE01_CCR_SHIFT 8
+#define TYPE01_CCR_MASK 0xffffff
+#define TYPE01_CPR_SHIFT 0
+#define TYPE01_CPR_MASK 0xff
+#define TYPE01_HTR_SHIFT 16
+#define TYPE01_HTR_MASK 0xff
+#define TYPE01_IPR_SHIFT 8
+#define TYPE01_IPR_MASK 0xFF
+#define TYPE01_ILR_SHIFT 0
+#define TYPE01_ILR_MASK 0xFF
+#define TYPE01_BCC_SHIFT 24
+
+#define HB_BASE_CLASS 0x06
+#define HB_SUB_CLASS 0x00
+
+/* Header type reg shifts and masks */
+#define HTR_HL_SHIFT 0x0
+#define HTR_HL_MASK 0x7f
+#define HTR_MFD_SHIFT 7
+#define HTR_MFD_MASK 0x1
+
+/* BAR offset */
+#define BAR0_OFFSET 0x10
+#define BAR_TYPE_0_MAX_OFFSET 0x24
+#define BAR_TYPE_1_MAX_OFFSET 0x14
+#define BAR_NP_TYPE 0x0
+#define BAR_P_TYPE 0x1
+#define BAR_64_BIT 0x1
+#define BAR_32_BIT 0x0
+#define BAR_REG(bar_reg_value) ((bar_reg_value >> 2) & 0x1)
+
+/* Type 1 Cfg reg offsets */
+#define TYPE1_PBN 0x18
+#define TYPE1_SEC_STA 0x1C
+#define TYPE1_NP_MEM 0x20
+#define TYPE1_P_MEM 0x24
+#define TYPE1_P_MEM_BU 0x28 /* Prefetchable Base Upper Offset */
+#define TYPE1_P_MEM_LU 0x2C /* Prefetchable Limit Upper Offset */
+
+/* Bus Number reg shifts */
+#define SECBN_SHIFT 8
+#define SUBBN_SHIFT 16
+
+/* Bus Number reg masks */
+#define PRIBN_MASK 0xff
+#define SECBN_MASK 0xff
+#define SUBBN_MASK 0xff
+#define SECBN_EXTRACT 0xffff00ff
+
+/* Capability header reg shifts */
+#define PCIE_CIDR_SHIFT 0
+#define PCIE_NCPR_SHIFT 8
+#define PCIE_ECAP_CIDR_SHIFT 0
+#define PCIE_ECAP_NCPR_SHIFT 20
+
+/* Capability header reg masks */
+#define PCIE_CIDR_MASK 0xff
+#define PCIE_NCPR_MASK 0xff
+#define PCIE_ECAP_CIDR_MASK 0xffff
+#define PCIE_ECAP_NCPR_MASK 0xfff
+
+#define PCIE_CAP_START 0x40
+#define PCIE_CAP_END 0xFC
+#define PCIE_ECAP_START 0x100
+#define PCIE_ECAP_END 0xFFC
+
+/* Capability Structure IDs */
+#define CID_PCIECS 0x10
+#define CID_MSI 0x05
+#define CID_MSIX 0x11
+#define CID_PMC 0x01
+#define CID_EA 0x14
+#define ECID_AER 0x0001
+#define ECID_RCECEA 0x0007
+#define ECID_ACS 0x000D
+#define ECID_ARICS 0x000E
+#define ECID_ATS 0x000F
+#define ECID_PRI 0x0013
+#define ECID_PASID 0x001B
+#define ECID_DPC 0x001D
+#define ECID_DVSEC 0x0023
+
+/* PCI Express capability struct offsets */
+#define CIDR_OFFSET 0x0
+#define PCIECR_OFFSET 0x2
+#define DCAPR_OFFSET 0x4
+#define ACSCR_OFFSET 0x4
+#define DCTLR_OFFSET 0x8
+#define LCAPR_OFFSET 0xC
+#define LCTRLR_OFFSET 0x10
+#define DCAP2R_OFFSET 0x24
+#define DCTL2R_OFFSET 0x28
+#define DCTL2R_MASK 0xFFFF
+#define LCAP2R_OFFSET 0x2C
+#define LCTL2R_OFFSET 0x30
+#define DCTL2R_MASK 0xFFFF
+#define DSTS_SHIFT 16
+#define DS_UNCORR_MASK 0x6
+#define DS_CORR_MASK 0x1
+
+/* PCIe capabilities reg shifts and masks */
+#define PCIECR_DPT_SHIFT 4
+#define PCIECR_DPT_MASK 0xf
+
+/* Device bitmask definitions */
+#define RCiEP (1 << 0b1001)
+#define RCEC (1 << 0b1010)
+#define EP (1 << 0b0000)
+#define RP (1 << 0b0100)
+#define UP (1 << 0b0101)
+#define DP (1 << 0b0110)
+#define iEP_EP (1 << 0b1100)
+#define iEP_RP (1 << 0b1011)
+#define PCI_PCIE (1 << 0b1000)
+#define PCIE_PCI (1 << 0b0111)
+#define PCIe_ALL (iEP_RP | iEP_EP | RP | EP | RCEC | RCiEP)
+
+#endif /* PCIE_SPEC_H */