coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
irq.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <device/pci.h>
6 #include <device/pci_def.h>
7 #include <device/pci_ops.h>
8 #include <intelblocks/gpio.h>
9 #include <intelblocks/irq.h>
10 #include <intelblocks/lpc_lib.h>
11 #include <soc/pci_devs.h>
13 #include <stdlib.h>
14 #include <types.h>
15 
16 #define MIN_SHARED_IRQ 16
17 #define MAX_SHARED_IRQ 23
18 #define TOTAL_SHARED_IRQ (MAX_SHARED_IRQ - MIN_SHARED_IRQ + 1)
19 #define MAX_IRQS 120
20 
21 #define IDX2PIN(i) (enum pci_pin)((i) + PCI_INT_A)
22 #define PIN2IDX(p) (size_t)((p) - PCI_INT_A)
23 
24 struct pin_info {
25  enum pin_state {
30  unsigned int usage_count;
31  unsigned int irq;
32 };
33 
34 static unsigned int irq_share_count[TOTAL_SHARED_IRQ];
35 
36 /*
37  * Assign PCI IRQs & pins according to controller rules.
38  *
39  * This information is provided to the FSP in order for it to do the
40  * programming; this is required because the FSP is also responsible for
41  * enabling some PCI devices so they will show up on their respective PCI
42  * buses. The FSP & PCH BIOS Specification contain rules for how certain IPs
43  * require their interrupt pin and interrupt line to be programmed.
44  *
45  * IOAPIC IRQs are used for PCI devices & GPIOs. The GPIO IRQs are fixed in
46  * hardware (the IRQ field is RO), and often start at 24, which means
47  * conflicts with PCI devices (if using the default FSP configuration) are very
48  * possible.
49  *
50  * These are the rules:
51  * 1) One entry per slot/function
52  * 2) Functions using PIRQs must use IOxAPIC IRQs 16-23
53  * 3) Single-function devices must use INTA
54  * 4) Each slot must have consistent INTx<->PIRQy mappings
55  * 5) Some functions have special interrupt pin requirements (FIXED_INT_ANY_PIRQ)
56  * 6) PCI Express RPs must be assigned in a special way (FIXED_INT_PIRQ)
57  * 7) Some functions require a unique IRQ number (mostly LPSS devices, DIRECT_IRQ)
58  * 8) PCI functions must avoid sharing an IRQ with a GPIO pad which routes its
59  * IRQ through IO-APIC.
60  */
61 
62 static int find_free_unique_irq(void)
63 {
64  static unsigned int next_irq = MAX_SHARED_IRQ + 1;
65 
66  while (next_irq < MAX_IRQS && gpio_routes_ioapic_irq(next_irq))
67  ++next_irq;
68 
69  if (next_irq == MAX_IRQS)
70  return INVALID_IRQ;
71 
72  return next_irq++;
73 }
74 
75 static enum pci_pin find_free_pin(const struct pin_info pin_info[PCI_INT_MAX])
76 {
77  for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
78  if (pin_info[pin_idx].pin_state == FREE_PIN)
79  return IDX2PIN(pin_idx);
80  }
81 
82  return PCI_INT_NONE;
83 }
84 
85 static enum pci_pin find_shareable_pin(const struct pin_info pin_info[PCI_INT_MAX])
86 {
87  unsigned int least_shared = 255;
88  int least_index = -1;
89 
90  for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
91  if (pin_info[pin_idx].pin_state == SHARED_IRQ_PIN &&
92  pin_info[pin_idx].usage_count < least_shared) {
93  least_shared = pin_info[pin_idx].usage_count;
94  least_index = pin_idx;
95  }
96  }
97 
98  if (least_index < 0)
99  return PCI_INT_NONE;
100 
101  return IDX2PIN(least_index);
102 }
103 
104 static enum pirq find_global_least_used_pirq(void)
105 {
106  unsigned int least_shared = 255;
107  int least_index = -1;
108 
109  for (size_t i = 0; i < TOTAL_SHARED_IRQ; i++) {
110  if (irq_share_count[i] < least_shared) {
111  least_shared = irq_share_count[i];
112  least_index = i;
113  }
114  }
115 
116  if (least_index >= 0)
117  return (enum pirq)least_index + PIRQ_A;
118 
119  return PIRQ_INVALID;
120 }
121 
122 
123 static int pirq_to_irq(enum pirq pirq)
124 {
125  return pirq_idx(pirq) + MIN_SHARED_IRQ;
126 }
127 
128 static bool assign_pirq(struct pin_info pin_info[PCI_INT_MAX], enum pci_pin pin, enum pirq pirq)
129 {
131  printk(BIOS_ERR, "Invalid pirq constraint %u\n", pirq);
132  return false;
133  }
134 
135  const int irq = pirq_to_irq(pirq);
136  pin_info[PIN2IDX(pin)].irq = irq;
138  return true;
139 }
140 
141 static bool assign_pin(enum pci_pin pin, unsigned int fn, enum pin_state state,
142  struct pin_info *pin_info,
143  enum pci_pin fn_pin_map[MAX_FNS])
144 {
145  if (pin < PCI_INT_A || pin > PCI_INT_D) {
146  printk(BIOS_ERR, "Invalid pin constraint %u\n", pin);
147  return false;
148  }
149 
150  const size_t pin_idx = PIN2IDX(pin);
151  pin_info[pin_idx].pin_state = state;
152  pin_info[pin_idx].usage_count++;
153  fn_pin_map[fn] = pin;
154 
155  return true;
156 }
157 
159  struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
160 {
161  for (size_t i = 0; i < MAX_FNS; i++) {
162  const enum pci_pin fixed_int_pin = constraints->fns[i].fixed_int_pin;
163  if (fixed_int_pin == PCI_INT_NONE)
164  continue;
165 
166  if (!assign_pin(fixed_int_pin, i, SHARED_IRQ_PIN, pin_info, fn_pin_map))
167  return false;
168  }
169 
170  return true;
171 }
172 
174  struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
175 {
176  for (size_t i = 0; i < MAX_FNS; i++) {
177  const enum pirq fixed_pirq = constraints->fns[i].fixed_pirq;
178  if (fixed_pirq == PIRQ_INVALID)
179  continue;
180 
181  /* A constraint with a fixed pirq is assumed to also have a
182  fixed pin */
183  const enum pci_pin pin = fn_pin_map[i];
184  if (pin == PCI_INT_NONE) {
185  printk(BIOS_ERR, "Slot %u, pirq %u, no pin for function %zu\n",
186  constraints->slot, fixed_pirq, i);
187  return false;
188  }
189 
190  if (!assign_pirq(pin_info, pin, fixed_pirq))
191  return false;
192  }
193 
194  return true;
195 }
196 
198  struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
199 {
200  for (size_t i = 0; i < MAX_FNS; i++) {
201  if (constraints->fns[i].irq_route != IRQ_DIRECT)
202  continue;
203 
204  enum pci_pin pin = find_free_pin(pin_info);
205  if (pin == PCI_INT_NONE)
206  return false;
207 
208  if (!assign_pin(pin, i, UNIQUE_IRQ_PIN, pin_info, fn_pin_map))
209  return false;
210 
211  const int irq = find_free_unique_irq();
212  if (irq == INVALID_IRQ) {
213  printk(BIOS_ERR, "No free unique IRQs found\n");
214  return false;
215  }
216 
217  const size_t pin_idx = PIN2IDX(pin);
218  pin_info[pin_idx].irq = irq;
219  }
220 
221  return true;
222 }
223 
225  struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
226 {
227  for (size_t i = 0; i < MAX_FNS; i++) {
228  if (constraints->fns[i].irq_route != IRQ_PIRQ)
229  continue;
230 
231  if (fn_pin_map[i] == PCI_INT_NONE) {
232  enum pci_pin pin = find_free_pin(pin_info);
233  if (pin == PCI_INT_NONE) {
235 
236  if (pin == PCI_INT_NONE) {
237  printk(BIOS_ERR, "No shareable pins found\n");
238  return false;
239  }
240  }
241 
242  if (!assign_pin(pin, i, SHARED_IRQ_PIN, pin_info, fn_pin_map))
243  return false;
244  }
245  }
246 
247  return true;
248 }
249 
251 {
252  for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
253  if (pin_info[pin_idx].pin_state != SHARED_IRQ_PIN || pin_info[pin_idx].irq != 0)
254  continue;
255 
257  if (pirq == PIRQ_INVALID)
258  return false;
259 
260  if (!assign_pirq(pin_info, IDX2PIN(pin_idx), pirq))
261  return false;
262  }
263 
264  return true;
265 }
266 
267 static void add_entry(struct pci_irq_entry **head, pci_devfn_t devfn, enum pci_pin pin,
268  unsigned int irq)
269 {
270  struct pci_irq_entry *entry = malloc(sizeof(*entry));
271  struct pci_irq_entry **tmp = head;
272 
273  entry->devfn = devfn;
274  entry->pin = pin;
275  entry->irq = irq;
276  entry->next = NULL;
277 
278  while (*tmp)
279  tmp = &(*tmp)->next;
280 
281  *tmp = entry;
282 }
283 
284 static void add_slot_entries(struct pci_irq_entry **head, unsigned int slot,
285  struct pin_info pin_info[PCI_INT_MAX],
286  const enum pci_pin fn_pin_map[MAX_FNS])
287 {
288  for (size_t fn = 0; fn < MAX_FNS; fn++) {
289  if (fn_pin_map[fn] == PCI_INT_NONE)
290  continue;
291 
292  const size_t pin_idx = PIN2IDX(fn_pin_map[fn]);
293  add_entry(head, PCI_DEVFN(slot, fn), fn_pin_map[fn], pin_info[pin_idx].irq);
294  }
295 }
296 
297 static bool assign_slot(struct pci_irq_entry **head,
298  const struct slot_irq_constraints *constraints)
299 {
300  struct pin_info pin_info[PCI_INT_MAX] = {0};
301  enum pci_pin fn_pin_map[MAX_FNS] = {0};
302 
303  /* The order in which pins are assigned is important in that strict constraints must
304  * be resolved first. This means fixed_int_pin -> fixed_pirq -> direct route ->
305  * shared pins -> shared pirqs
306  */
307  if (!assign_fixed_pins(constraints, pin_info, fn_pin_map))
308  return false;
309 
310  if (!assign_fixed_pirqs(constraints, pin_info, fn_pin_map))
311  return false;
312 
313  if (!assign_direct_irqs(constraints, pin_info, fn_pin_map))
314  return false;
315 
316  if (!assign_shareable_pins(constraints, pin_info, fn_pin_map))
317  return false;
318 
319  if (!assign_pirqs(pin_info))
320  return false;
321 
322  add_slot_entries(head, constraints->slot, pin_info, fn_pin_map);
323  return true;
324 }
325 
327 
328 bool assign_pci_irqs(const struct slot_irq_constraints *constraints, size_t num_slots)
329 {
330  for (size_t i = 0; i < num_slots; i++) {
332  return false;
333  }
334 
335  const struct pci_irq_entry *entry = cached_entries;
336  while (entry) {
337  printk(BIOS_INFO, "PCI %2X.%X, %s, using IRQ #%d\n",
338  PCI_SLOT(entry->devfn), PCI_FUNC(entry->devfn),
339  pin_to_str(entry->pin), entry->irq);
340 
341  entry = entry->next;
342  }
343 
344  return true;
345 }
346 
348 {
349  return cached_entries;
350 }
351 
352 static enum pirq irq_to_pirq(unsigned int irq)
353 {
354  if (irq >= MIN_SHARED_IRQ && irq <= MAX_SHARED_IRQ)
355  return (enum pirq)(irq - MIN_SHARED_IRQ + PIRQ_A);
356  else
357  /*
358  * Unknown if devices that require unique IRQs will
359  * even work in legacy PIC mode, given they cannot map
360  * to a PIRQ, therefore skip adding an entry.
361  */
362  return PIRQ_INVALID;
363 }
364 
366 {
367  struct slot_pin_irq_map *pin_irq_map;
368  const uint8_t *legacy_pirq_routing;
369  struct pic_pirq_map pirq_map = {0};
370  size_t map_count = 0;
371  size_t pirq_routes;
372  size_t i;
373 
374  if (!cached_entries)
375  return false;
376 
377  pin_irq_map = calloc(MAX_SLOTS, sizeof(struct slot_pin_irq_map) * PCI_INT_MAX);
378 
379  pirq_map.type = PIRQ_GSI;
380  legacy_pirq_routing = lpc_get_pic_pirq_routing(&pirq_routes);
381  for (i = 0; i < PIRQ_COUNT && i < pirq_routes; i++)
382  pirq_map.gsi[i] = legacy_pirq_routing[i];
383 
384  const struct pci_irq_entry *entry = cached_entries;
385  while (entry) {
386  const unsigned int slot = PCI_SLOT(entry->devfn);
387 
388  if (is_slot_pin_assigned(pin_irq_map, map_count, slot, entry->pin)) {
389  entry = entry->next;
390  continue;
391  }
392 
393  pin_irq_map[map_count].slot = slot;
394  pin_irq_map[map_count].pin = entry->pin;
395  pin_irq_map[map_count].apic_gsi = entry->irq;
396  pin_irq_map[map_count].pic_pirq = irq_to_pirq(entry->irq);
397  map_count++;
398  entry = entry->next;
399  }
400 
401  intel_write_pci0_PRT(pin_irq_map, map_count, &pirq_map);
402  free(pin_irq_map);
403 
404  return true;
405 }
406 
408 {
409  const struct pci_irq_entry *entry = cached_entries;
410 
411  if (!entry)
412  return false;
413 
414  while (entry) {
415  if (PCI_SLOT(entry->devfn) >= MIN_PCH_SLOT) {
416  entry = entry->next;
417  continue;
418  }
419 
420  if (entry->irq) {
421  pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(entry->devfn),
422  PCI_FUNC(entry->devfn));
425  }
426 
427  entry = entry->next;
428  }
429 
430  return true;
431 }
432 
433 int get_pci_devfn_irq(unsigned int devfn)
434 {
435  const struct pci_irq_entry *entry = cached_entries;
436 
437  while (entry) {
438  if (entry->devfn == devfn)
439  return entry->irq;
440 
441  entry = entry->next;
442  }
443 
444  return INVALID_IRQ;
445 }
bool is_slot_pin_assigned(const struct slot_pin_irq_map *pin_irq_map, unsigned int map_count, unsigned int slot, enum pci_pin pin)
Definition: acpi_pirq_gen.c:69
void intel_write_pci0_PRT(const struct slot_pin_irq_map *pin_irq_map, unsigned int map_count, const struct pic_pirq_map *pirq_map)
Definition: acpi_pirq_gen.c:46
#define MAX_SLOTS
Definition: acpi_pirq_gen.h:9
pirq
Definition: acpi_pirq_gen.h:20
@ PIRQ_A
Definition: acpi_pirq_gen.h:22
@ PIRQ_H
Definition: acpi_pirq_gen.h:29
@ PIRQ_INVALID
Definition: acpi_pirq_gen.h:21
@ PIRQ_COUNT
Definition: acpi_pirq_gen.h:30
@ PIRQ_GSI
Definition: acpi_pirq_gen.h:66
static size_t pirq_idx(enum pirq pirq)
Definition: acpi_pirq_gen.h:33
pci_pin
Definition: acpi_pirq_gen.h:11
@ PCI_INT_D
Definition: acpi_pirq_gen.h:16
@ PCI_INT_NONE
Definition: acpi_pirq_gen.h:12
@ PCI_INT_MAX
Definition: acpi_pirq_gen.h:17
#define MAX_FNS
Definition: irq.h:9
#define INVALID_IRQ
Definition: irq.h:10
#define MAX_IRQS
Definition: irq.c:19
static bool assign_fixed_pirqs(const struct slot_irq_constraints *constraints, struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:173
static bool assign_direct_irqs(const struct slot_irq_constraints *constraints, struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:197
bool generate_pin_irq_map(void)
Definition: irq.c:365
int get_pci_devfn_irq(unsigned int devfn)
Definition: irq.c:433
static bool assign_slot(struct pci_irq_entry **head, const struct slot_irq_constraints *constraints)
Definition: irq.c:297
bool irq_program_non_pch(void)
Definition: irq.c:407
static enum pirq irq_to_pirq(unsigned int irq)
Definition: irq.c:352
static int pirq_to_irq(enum pirq pirq)
Definition: irq.c:123
static bool assign_pirq(struct pin_info pin_info[PCI_INT_MAX], enum pci_pin pin, enum pirq pirq)
Definition: irq.c:128
#define PIN2IDX(p)
Definition: irq.c:22
static unsigned int irq_share_count[TOTAL_SHARED_IRQ]
Definition: irq.c:34
static void add_slot_entries(struct pci_irq_entry **head, unsigned int slot, struct pin_info pin_info[PCI_INT_MAX], const enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:284
#define IDX2PIN(i)
Definition: irq.c:21
static bool assign_fixed_pins(const struct slot_irq_constraints *constraints, struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:158
bool assign_pci_irqs(const struct slot_irq_constraints *constraints, size_t num_slots)
Definition: irq.c:328
#define MAX_SHARED_IRQ
Definition: irq.c:17
static struct pci_irq_entry * cached_entries
Definition: irq.c:326
#define TOTAL_SHARED_IRQ
Definition: irq.c:18
#define MIN_SHARED_IRQ
Definition: irq.c:16
const struct pci_irq_entry * get_cached_pci_irqs(void)
Definition: irq.c:347
static void add_entry(struct pci_irq_entry **head, pci_devfn_t devfn, enum pci_pin pin, unsigned int irq)
Definition: irq.c:267
static bool assign_shareable_pins(const struct slot_irq_constraints *constraints, struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:224
static bool assign_pirqs(struct pin_info pin_info[PCI_INT_MAX])
Definition: irq.c:250
static enum pci_pin find_shareable_pin(const struct pin_info pin_info[PCI_INT_MAX])
Definition: irq.c:85
static enum pirq find_global_least_used_pirq(void)
Definition: irq.c:104
static enum pci_pin find_free_pin(const struct pin_info pin_info[PCI_INT_MAX])
Definition: irq.c:75
static bool assign_pin(enum pci_pin pin, unsigned int fn, enum pin_state state, struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
Definition: irq.c:141
static int find_free_unique_irq(void)
Definition: irq.c:62
#define printk(level,...)
Definition: stdlib.h:16
void * malloc(size_t size)
Definition: malloc.c:53
void * calloc(size_t nitems, size_t size)
Definition: malloc.c:58
void free(void *ptr)
Definition: malloc.c:67
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
const uint8_t * lpc_get_pic_pirq_routing(size_t *num)
Definition: lpc_lib.c:326
state
Definition: raminit.c:1787
#define PCI_DEVFN(slot, func)
Definition: pci_def.h:548
#define PCI_INTERRUPT_PIN
Definition: pci_def.h:95
#define PCI_INTERRUPT_LINE
Definition: pci_def.h:94
#define PCI_FUNC(devfn)
Definition: pci_def.h:550
#define PCI_SLOT(devfn)
Definition: pci_def.h:549
const char * pin_to_str(int pin)
Take an INT_PIN number (0, 1 - 4) and convert it to a string ("NO PIN", "PIN A" - "PIN D")
Definition: pci_device.c:1628
static __always_inline void pci_s_write_config8(pci_devfn_t dev, uint16_t reg, uint8_t value)
Definition: pci_io_cfg.h:98
#define PCI_DEV(SEGBUS, DEV, FN)
Definition: pci_type.h:14
u32 pci_devfn_t
Definition: pci_type.h:8
#define MIN_PCH_SLOT
Definition: pci_devs.h:84
bool gpio_routes_ioapic_irq(uint32_t irq)
Definition: gpio.c:232
#define NULL
Definition: stddef.h:19
unsigned char uint8_t
Definition: stdint.h:8
Definition: irq.h:38
enum pci_pin pin
Definition: irq.h:40
unsigned int devfn
Definition: irq.h:39
unsigned int irq
Definition: irq.h:41
struct pci_irq_entry * next
Definition: irq.h:42
enum pirq_map_type type
Definition: acpi_pirq_gen.h:75
unsigned int gsi[PIRQ_COUNT]
Definition: acpi_pirq_gen.h:77
Definition: irq.c:24
pin_state
Definition: irq.c:25
@ FREE_PIN
Definition: irq.c:26
@ SHARED_IRQ_PIN
Definition: irq.c:27
@ UNIQUE_IRQ_PIN
Definition: irq.c:28
unsigned int irq
Definition: irq.c:31
unsigned int usage_count
Definition: irq.c:30
unsigned int apic_gsi
Definition: acpi_pirq_gen.h:62
unsigned int slot
Definition: acpi_pirq_gen.h:57
unsigned int pic_pirq
Definition: acpi_pirq_gen.h:60
enum pci_pin pin
Definition: acpi_pirq_gen.h:58