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