1 /*
2  * Copyright (c) 2006-2022, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2022-08-25     GuEe-GUI     first version
9  */
10 
11 #ifndef __PCI_MSI_H__
12 #define __PCI_MSI_H__
13 
14 #include <drivers/pci.h>
15 
16 /*
17  * MSI Format:
18  *  T0: 32-bit Address
19  *  T1: 64-bit Address
20  *  T2: 32-bit Address with Per-Vector Masking
21  *  T3: 64-bit Address with Per-Vector Masking
22  *
23  *   31                      16  15              8 7             0
24  *  +---------------------------+-----------------+---------------+
25  *  |      Message Control      | Next Capability | Capability ID | DW0
26  *  |                           |     Pointer     |     (05h)     |
27  *  +---------------------------+-----------------+---------------+
28  *  |                    Message Address [31:0]                   | DW1
29  *  +-------------------------------------------------------------+
30  *  |                    Message Address [63:32]                  | DW2 (T1: only 64-bit)
31  *  +---------------------------+---------------------------------+
32  *  |         Reserved          |           Message Data          | DW3
33  *  +---------------------------+---------------------------------+
34  *  |                       Mask Bits                             | DW4 (T2/T3: only with Per-Vector Masking)
35  *  +-------------------------------------------------------------+
36  *  |                      Pending Bits                           | DW5 (T2/T3: only with Per-Vector Masking)
37  *  +-------------------------------------------------------------+
38  *
39  * MSI Message Control:
40  *
41  *   15                   9  8   7  6             4 3        1  0
42  *  +----------------------+---+---+---------------+----------+---+
43  *  |       Reserved       |   |   |               |          |   |
44  *  +----------------------+---+---+---------------+----------+---+
45  *                           ^   ^         ^             ^      ^
46  *                           |   |         |             |      |
47  *                           |   |         |             |      +---- MSI Enable (RW)
48  *                           |   |         |             +----------- Multiple Message Capable (RO, log2n, [n <= 5])
49  *                           |   |         +------------------------- Multiple Message Enable (RW, log2n, [n <= 5])
50  *                           |   +----------------------------------- 64-bit Address Capable
51  *                           +--------------------------------------- Per-Vector Masking Capable
52  */
53 
54 struct rt_pci_msi_conf
55 {
56     rt_uint32_t mask;
57     rt_uint8_t mask_pos;
58     int default_irq;
59 
60     struct
61     {
62         rt_uint8_t is_masking:1;
63         rt_uint8_t is_64bit:1;
64         rt_uint8_t multi_msg_max:3; /* log2 num of messages allocated */
65         rt_uint8_t multi_msg_use:3; /* log2 num of messages supported */
66     } cap;
67 };
68 
69 /*
70  * MSI-X Format:
71  *
72  *   31                      16  15              8 7             0
73  *  +---------------------------+-----------------+---------------+
74  *  |      Message Control      | Next Capability | Capability ID | DW0
75  *  |                           |     Pointer     |     (11h)     |
76  *  +---------------------------+-----------------+---+-----------+
77  *  |                    MSI-X Table Offset           | Table BIR | DW1 (BIR: BAR Index Register)
78  *  +-------------------------------------------------+-----------+               |
79  *  |             Pending Bit Array (PBA) Offset      |  PBA BIR  | DW2 --------+ |
80  *  +-------------------------------------------------+-----------+             | |
81  *                                                                              | |
82  * MSI-X Message Control:                                                       | |
83  *                                                                              | |
84  *   15 14 13      11 10                                         0              | |
85  *  +---+---+----------+------------------------------------------+             | |
86  *  |   |   | Reserved |         Table Size in N-1 (RO)           |             | |
87  *  +---+---+----------+------------------------------------------+             | |
88  *    ^   ^                                                                     | |
89  *    |   |                                                                     | |
90  *    |   +---- Function Mask (RW)                                              | |
91  *    +-------- MSI-X Enable (RW)                                               | |
92  *                                                                              | |
93  * MSI-X Table (BAR[Table BIR] + MSI-X Table Offset):                           | |
94  *                                                                              | |
95  *          DW3            DW2             DW1             DW0                  | |
96  *  +----------------+--------------+---------------+---------------+ <---------|-+
97  *  | Vector Control | Message Data | Upper Address | Lower Address | Entry 0   |
98  *  +----------------+--------------+---------------+---------------+           |
99  *  | Vector Control | Message Data | Upper Address | Lower Address | Entry 1   |
100  *  +----------------+--------------+---------------+---------------+           |
101  *  |     ......     |    ......    |    ......     |    ......     |           |
102  *  +----------------+--------------+---------------+---------------+           |
103  *  | Vector Control | Message Data | Upper Address | Lower Address | Entry N-1 |
104  *  +----------------+--------------+---------------+---------------+           |
105  *                  ^                                                           |
106  *                  |                                                           |
107  *                  +---- Bit 0 is vector Mask Bit (R/W)                        |
108  *                                                                              |
109  * MSI-X Pending Bit Array (BAR[PBA BIR] + Pending Bit Array Offset):           |
110  *                                                                              |
111  *          DW1            DW0                                                  |
112  *  +-------------------------------+ <-----------------------------------------+
113  *  |     Pending Bits 0 - 63       | QW 0
114  *  +-------------------------------+
115  *  |    Pending Bits 64 - 127      | QW 1
116  *  +-------------------------------+
117  *  |            ......             |
118  *  +-------------------------------+
119  *  |         Pending Bits          | QW (N-1)/64
120  *  +-------------------------------+
121  */
122 
123 struct rt_pci_msix_conf
124 {
125     int index;
126 
127     rt_uint32_t msg_ctrl;
128     void *table_base;
129 };
130 
131 struct rt_pci_msi_msg
132 {
133     rt_uint32_t address_lo;
134     rt_uint32_t address_hi;
135     rt_uint32_t data;
136 };
137 
138 struct rt_pci_msi_desc
139 {
140     rt_list_t list;
141 
142     int irq;
143     rt_size_t vector_used;
144     rt_size_t vector_count;
145 
146     union
147     {
148         /* For MSI-X */
149         rt_bitmap_t *affinity;
150         /* For MSI */
151         rt_bitmap_t **affinities;
152     };
153 
154     struct rt_pci_device *pdev;
155     struct rt_pci_msi_msg msg;
156 
157     void *write_msi_msg_data;
158     void (*write_msi_msg)(struct rt_pci_msi_desc *, void *);
159 
160     rt_bool_t is_msix;
161     union
162     {
163         struct rt_pci_msi_conf msi;
164         struct rt_pci_msix_conf msix;
165     };
166 
167     void *priv;
168 };
169 
170 #define rt_pci_msi_first_desc(pdev) \
171     (rt_list_isempty(&(pdev)->msi_desc_nodes) ? RT_NULL : \
172         rt_list_first_entry(&(pdev)->msi_desc_nodes, struct rt_pci_msi_desc, list))
173 
174 #define rt_pci_msi_for_each_desc(pdev, desc) \
175     rt_list_for_each_entry(desc, &(pdev)->msi_desc_nodes, list)
176 
177 #define rt_pci_msix_table_size(flags) ((flags & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
178 
179 rt_err_t rt_pci_msi_setup_irqs(struct rt_pci_device *pdev, int nvec, int type);
180 
181 void rt_pci_msi_shutdown(struct rt_pci_device *pdev);
182 void rt_pci_msix_shutdown(struct rt_pci_device *pdev);
183 void rt_pci_msi_free_irqs(struct rt_pci_device *pdev);
184 void rt_pci_msi_write_msg(struct rt_pci_msi_desc *desc, struct rt_pci_msi_msg *msg);
185 
186 void rt_pci_msi_mask_irq(struct rt_pic_irq *pirq);
187 void rt_pci_msi_unmask_irq(struct rt_pic_irq *pirq);
188 
189 #endif /* __PCI_MSI_H__ */
190