1 /* 2 * Copyright (c) 2019 Intel Corporation 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ 8 #define ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ 9 10 /** 11 * @brief PCIe Host MSI Interface 12 * @defgroup pcie_host_msi_interface PCIe Host MSI Interface 13 * @ingroup pcie_host_interface 14 * @{ 15 */ 16 17 #include <zephyr/kernel.h> 18 #include <zephyr/types.h> 19 #include <stdbool.h> 20 21 #include <zephyr/drivers/pcie/pcie.h> 22 23 #ifdef __cplusplus 24 extern "C" { 25 #endif 26 27 #ifdef CONFIG_PCIE_CONTROLLER 28 struct msi_vector_generic { 29 unsigned int irq; 30 uint32_t address; 31 uint16_t eventid; 32 unsigned int priority; 33 }; 34 35 typedef struct msi_vector_generic arch_msi_vector_t; 36 37 #define PCI_DEVID(bus, dev, fn) ((((bus) & 0xff) << 8) | (((dev) & 0x1f) << 3) | ((fn) & 0x07)) 38 #define PCI_BDF_TO_DEVID(bdf) PCI_DEVID(PCIE_BDF_TO_BUS(bdf), \ 39 PCIE_BDF_TO_DEV(bdf), \ 40 PCIE_BDF_TO_FUNC(bdf)) 41 42 #endif 43 44 struct msix_vector { 45 uint32_t msg_addr; 46 uint32_t msg_up_addr; 47 uint32_t msg_data; 48 uint32_t vector_ctrl; 49 } __packed; 50 51 struct msi_vector { 52 pcie_bdf_t bdf; 53 arch_msi_vector_t arch; 54 #ifdef CONFIG_PCIE_MSI_X 55 struct msix_vector *msix_vector; 56 bool msix; 57 #endif /* CONFIG_PCIE_MSI_X */ 58 }; 59 60 typedef struct msi_vector msi_vector_t; 61 62 #ifdef CONFIG_PCIE_MSI_MULTI_VECTOR 63 64 /** 65 * @brief Allocate vector(s) for the endpoint MSI message(s) 66 * 67 * @param bdf the target PCI endpoint 68 * @param priority the MSI vectors base interrupt priority 69 * @param vectors an array for storing allocated MSI vectors 70 * @param n_vector the size of the MSI vectors array 71 * 72 * @return the number of allocated MSI vectors. 73 */ 74 extern uint8_t pcie_msi_vectors_allocate(pcie_bdf_t bdf, 75 unsigned int priority, 76 msi_vector_t *vectors, 77 uint8_t n_vector); 78 79 /** 80 * @brief Connect the MSI vector to the handler 81 * 82 * @param bdf the target PCI endpoint 83 * @param vector the MSI vector to connect 84 * @param routine Interrupt service routine 85 * @param parameter ISR parameter 86 * @param flags Arch-specific IRQ configuration flag 87 * 88 * @return True on success, false otherwise 89 */ 90 extern bool pcie_msi_vector_connect(pcie_bdf_t bdf, 91 msi_vector_t *vector, 92 void (*routine)(const void *parameter), 93 const void *parameter, 94 uint32_t flags); 95 96 #endif /* CONFIG_PCIE_MSI_MULTI_VECTOR */ 97 98 /** 99 * @brief Compute the target address for an MSI posted write. 100 * 101 * This function is exported by the arch, board or SoC code. 102 * 103 * @param irq The IRQ we wish to trigger via MSI. 104 * @param vector The vector for which you want the address (or NULL) 105 * @param n_vector the size of the vector array 106 * @return A (32-bit) value for the MSI MAP register. 107 */ 108 extern uint32_t pcie_msi_map(unsigned int irq, 109 msi_vector_t *vector, 110 uint8_t n_vector); 111 112 /** 113 * @brief Compute the data for an MSI posted write. 114 * 115 * This function is exported by the arch, board or SoC code. 116 * 117 * @param irq The IRQ we wish to trigger via MSI. 118 * @param vector The vector for which you want the data (or NULL) 119 * @return A (16-bit) value for MSI MDR register. 120 */ 121 extern uint16_t pcie_msi_mdr(unsigned int irq, 122 msi_vector_t *vector); 123 124 /** 125 * @brief Configure the given PCI endpoint to generate MSIs. 126 * 127 * @param bdf the target PCI endpoint 128 * @param vectors an array of allocated vector(s) 129 * @param n_vector the size of the vector array 130 * @param irq The IRQ we wish to trigger via MSI. 131 * @return true if the endpoint supports MSI, false otherwise. 132 */ 133 extern bool pcie_msi_enable(pcie_bdf_t bdf, 134 msi_vector_t *vectors, 135 uint8_t n_vector, 136 unsigned int irq); 137 138 /** 139 * @brief Check if the given PCI endpoint supports MSI/MSI-X 140 * 141 * @param bdf the target PCI endpoint 142 * @return true if the endpoint support MSI/MSI-X 143 */ 144 extern bool pcie_is_msi(pcie_bdf_t bdf); 145 146 /* 147 * The first word of the MSI capability is shared with the 148 * capability ID and list link. The high 16 bits are the MCR. 149 */ 150 151 #define PCIE_MSI_MCR 0U 152 153 #define PCIE_MSI_MCR_EN 0x00010000U /* enable MSI */ 154 #define PCIE_MSI_MCR_MMC 0x000E0000U /* Multi Messages Capable mask */ 155 #define PCIE_MSI_MCR_MMC_SHIFT 17 156 #define PCIE_MSI_MCR_MME 0x00700000U /* mask of # of enabled IRQs */ 157 #define PCIE_MSI_MCR_MME_SHIFT 20 158 #define PCIE_MSI_MCR_64 0x00800000U /* 64-bit MSI */ 159 160 /* 161 * The MAP follows the MCR. If PCIE_MSI_MCR_64, then the MAP 162 * is two words long. The MDR follows immediately after the MAP. 163 */ 164 165 #define PCIE_MSI_MAP0 1U 166 #define PCIE_MSI_MAP1_64 2U 167 #define PCIE_MSI_MDR_32 2U 168 #define PCIE_MSI_MDR_64 3U 169 170 /* 171 * As for MSI, he first word of the MSI-X capability is shared 172 * with the capability ID and list link. The high 16 bits are the MCR. 173 */ 174 175 #define PCIE_MSIX_MCR 0U 176 177 #define PCIE_MSIX_MCR_EN 0x80000000U /* Enable MSI-X */ 178 #define PCIE_MSIX_MCR_FMASK 0x40000000U /* Function Mask */ 179 #define PCIE_MSIX_MCR_TSIZE 0x07FF0000U /* Table size mask */ 180 #define PCIE_MSIX_MCR_TSIZE_SHIFT 16 181 #define PCIE_MSIR_TABLE_ENTRY_SIZE 16 182 183 #define PCIE_MSIX_TR 1U 184 #define PCIE_MSIX_TR_BIR 0x00000007U /* Table BIR mask */ 185 #define PCIE_MSIX_TR_OFFSET 0xFFFFFFF8U /* Offset mask */ 186 187 #define PCIE_MSIX_PBA 2U 188 #define PCIE_MSIX_PBA_BIR 0x00000007U /* PBA BIR mask */ 189 #define PCIE_MSIX_PBA_OFFSET 0xFFFFFFF8U /* Offset mask */ 190 191 #define PCIE_VTBL_MA 0U /* Msg Address offset */ 192 #define PCIE_VTBL_MUA 4U /* Msg Upper Address offset */ 193 #define PCIE_VTBL_MD 8U /* Msg Data offset */ 194 #define PCIE_VTBL_VCTRL 12U /* Vector control offset */ 195 196 #ifdef __cplusplus 197 } 198 #endif 199 200 /** 201 * @} 202 */ 203 204 #endif /* ZEPHYR_INCLUDE_DRIVERS_PCIE_MSI_H_ */ 205