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