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