cbfs: Remove remnants of ext-win-*
[coreboot.git] / src / soc / intel / common / block / irq / irq.c
blobb1ceb0a88c2861984be517d9dd2b5a34ba1c4a8b
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <console/console.h>
4 #include <device/pci.h>
5 #include <device/pci_ops.h>
6 #include <intelblocks/gpio.h>
7 #include <intelblocks/irq.h>
8 #include <intelblocks/lpc_lib.h>
9 #include <soc/pci_devs.h>
10 #include <southbridge/intel/common/acpi_pirq_gen.h>
11 #include <stdlib.h>
12 #include <types.h>
14 #define MIN_SHARED_IRQ 16
15 #define MAX_SHARED_IRQ 23
16 #define TOTAL_SHARED_IRQ (MAX_SHARED_IRQ - MIN_SHARED_IRQ + 1)
17 #define MAX_IRQS 120
19 #define IDX2PIN(i) (enum pci_pin)((i) + PCI_INT_A)
20 #define PIN2IDX(p) (size_t)((p) - PCI_INT_A)
22 struct pin_info {
23 enum pin_state {
24 FREE_PIN,
25 SHARED_IRQ_PIN,
26 UNIQUE_IRQ_PIN,
27 } pin_state;
28 unsigned int usage_count;
29 unsigned int irq;
32 static unsigned int irq_share_count[TOTAL_SHARED_IRQ];
35 * Assign PCI IRQs & pins according to controller rules.
37 * This information is provided to the FSP in order for it to do the
38 * programming; this is required because the FSP is also responsible for
39 * enabling some PCI devices so they will show up on their respective PCI
40 * buses. The FSP & PCH BIOS Specification contain rules for how certain IPs
41 * require their interrupt pin and interrupt line to be programmed.
43 * IOAPIC IRQs are used for PCI devices & GPIOs. The GPIO IRQs are fixed in
44 * hardware (the IRQ field is RO), and often start at 24, which means
45 * conflicts with PCI devices (if using the default FSP configuration) are very
46 * possible.
48 * These are the rules:
49 * 1) One entry per slot/function
50 * 2) Functions using PIRQs must use IOxAPIC IRQs 16-23
51 * 3) Single-function devices must use INTA
52 * 4) Each slot must have consistent INTx<->PIRQy mappings
53 * 5) Some functions have special interrupt pin requirements (FIXED_INT_ANY_PIRQ)
54 * 6) PCI Express RPs must be assigned in a special way (FIXED_INT_PIRQ)
55 * 7) Some functions require a unique IRQ number (mostly LPSS devices, DIRECT_IRQ)
56 * 8) PCI functions must avoid sharing an IRQ with a GPIO pad which routes its
57 * IRQ through IO-APIC.
60 static int find_free_unique_irq(void)
62 static unsigned int next_irq = MAX_SHARED_IRQ + 1;
64 while (next_irq < MAX_IRQS && gpio_routes_ioapic_irq(next_irq))
65 ++next_irq;
67 if (next_irq == MAX_IRQS)
68 return INVALID_IRQ;
70 return next_irq++;
73 static enum pci_pin find_free_pin(const struct pin_info pin_info[PCI_INT_MAX])
75 for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
76 if (pin_info[pin_idx].pin_state == FREE_PIN)
77 return IDX2PIN(pin_idx);
80 return PCI_INT_NONE;
83 static enum pci_pin find_shareable_pin(const struct pin_info pin_info[PCI_INT_MAX])
85 unsigned int least_shared = 255;
86 int least_index = -1;
88 for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
89 if (pin_info[pin_idx].pin_state == SHARED_IRQ_PIN &&
90 pin_info[pin_idx].usage_count < least_shared) {
91 least_shared = pin_info[pin_idx].usage_count;
92 least_index = pin_idx;
96 if (least_index < 0)
97 return PCI_INT_NONE;
99 return IDX2PIN(least_index);
102 static enum pirq find_global_least_used_pirq(void)
104 unsigned int least_shared = 255;
105 int least_index = -1;
107 for (size_t i = 0; i < TOTAL_SHARED_IRQ; i++) {
108 if (irq_share_count[i] < least_shared) {
109 least_shared = irq_share_count[i];
110 least_index = i;
114 if (least_index >= 0)
115 return (enum pirq)least_index + PIRQ_A;
117 return PIRQ_INVALID;
121 static int pirq_to_irq(enum pirq pirq)
123 return pirq_idx(pirq) + MIN_SHARED_IRQ;
126 static bool assign_pirq(struct pin_info pin_info[PCI_INT_MAX], enum pci_pin pin, enum pirq pirq)
128 if (pirq < PIRQ_A || pirq > PIRQ_H) {
129 printk(BIOS_ERR, "Invalid pirq constraint %u\n", pirq);
130 return false;
133 const int irq = pirq_to_irq(pirq);
134 pin_info[PIN2IDX(pin)].irq = irq;
135 irq_share_count[pirq_idx(pirq)]++;
136 return true;
139 static bool assign_pin(enum pci_pin pin, unsigned int fn, enum pin_state state,
140 struct pin_info *pin_info,
141 enum pci_pin fn_pin_map[MAX_FNS])
143 if (pin < PCI_INT_A || pin > PCI_INT_D) {
144 printk(BIOS_ERR, "Invalid pin constraint %u\n", pin);
145 return false;
148 const size_t pin_idx = PIN2IDX(pin);
149 pin_info[pin_idx].pin_state = state;
150 pin_info[pin_idx].usage_count++;
151 fn_pin_map[fn] = pin;
153 return true;
156 static bool assign_fixed_pins(const struct slot_irq_constraints *constraints,
157 struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
159 for (size_t i = 0; i < MAX_FNS; i++) {
160 const enum pci_pin fixed_int_pin = constraints->fns[i].fixed_int_pin;
161 if (fixed_int_pin == PCI_INT_NONE)
162 continue;
164 if (!assign_pin(fixed_int_pin, i, SHARED_IRQ_PIN, pin_info, fn_pin_map))
165 return false;
168 return true;
171 static bool assign_fixed_pirqs(const struct slot_irq_constraints *constraints,
172 struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
174 for (size_t i = 0; i < MAX_FNS; i++) {
175 const enum pirq fixed_pirq = constraints->fns[i].fixed_pirq;
176 if (fixed_pirq == PIRQ_INVALID)
177 continue;
179 /* A constraint with a fixed pirq is assumed to also have a
180 fixed pin */
181 const enum pci_pin pin = fn_pin_map[i];
182 if (pin == PCI_INT_NONE) {
183 printk(BIOS_ERR, "Slot %u, pirq %u, no pin for function %zu\n",
184 constraints->slot, fixed_pirq, i);
185 return false;
188 if (!assign_pirq(pin_info, pin, fixed_pirq))
189 return false;
192 return true;
195 static bool assign_direct_irqs(const struct slot_irq_constraints *constraints,
196 struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
198 for (size_t i = 0; i < MAX_FNS; i++) {
199 if (constraints->fns[i].irq_route != IRQ_DIRECT)
200 continue;
202 enum pci_pin pin = find_free_pin(pin_info);
203 if (pin == PCI_INT_NONE)
204 return false;
206 if (!assign_pin(pin, i, UNIQUE_IRQ_PIN, pin_info, fn_pin_map))
207 return false;
209 const int irq = find_free_unique_irq();
210 if (irq == INVALID_IRQ) {
211 printk(BIOS_ERR, "No free unique IRQs found\n");
212 return false;
215 const size_t pin_idx = PIN2IDX(pin);
216 pin_info[pin_idx].irq = irq;
219 return true;
222 static bool assign_shareable_pins(const struct slot_irq_constraints *constraints,
223 struct pin_info *pin_info, enum pci_pin fn_pin_map[MAX_FNS])
225 for (size_t i = 0; i < MAX_FNS; i++) {
226 if (constraints->fns[i].irq_route != IRQ_PIRQ)
227 continue;
229 if (fn_pin_map[i] == PCI_INT_NONE) {
230 enum pci_pin pin = find_free_pin(pin_info);
231 if (pin == PCI_INT_NONE) {
232 pin = find_shareable_pin(pin_info);
234 if (pin == PCI_INT_NONE) {
235 printk(BIOS_ERR, "No shareable pins found\n");
236 return false;
240 if (!assign_pin(pin, i, SHARED_IRQ_PIN, pin_info, fn_pin_map))
241 return false;
245 return true;
248 static bool assign_pirqs(struct pin_info pin_info[PCI_INT_MAX])
250 for (size_t pin_idx = 0; pin_idx < PCI_INT_MAX; pin_idx++) {
251 if (pin_info[pin_idx].pin_state != SHARED_IRQ_PIN || pin_info[pin_idx].irq != 0)
252 continue;
254 enum pirq pirq = find_global_least_used_pirq();
255 if (pirq == PIRQ_INVALID)
256 return false;
258 if (!assign_pirq(pin_info, IDX2PIN(pin_idx), pirq))
259 return false;
262 return true;
265 static void add_entry(struct pci_irq_entry **head, pci_devfn_t devfn, enum pci_pin pin,
266 unsigned int irq)
268 struct pci_irq_entry *entry = malloc(sizeof(*entry));
269 struct pci_irq_entry **tmp = head;
271 entry->devfn = devfn;
272 entry->pin = pin;
273 entry->irq = irq;
274 entry->next = NULL;
276 while (*tmp)
277 tmp = &(*tmp)->next;
279 *tmp = entry;
282 static void add_slot_entries(struct pci_irq_entry **head, unsigned int slot,
283 struct pin_info pin_info[PCI_INT_MAX],
284 const enum pci_pin fn_pin_map[MAX_FNS])
286 for (size_t fn = 0; fn < MAX_FNS; fn++) {
287 if (fn_pin_map[fn] == PCI_INT_NONE)
288 continue;
290 const size_t pin_idx = PIN2IDX(fn_pin_map[fn]);
291 add_entry(head, PCI_DEVFN(slot, fn), fn_pin_map[fn], pin_info[pin_idx].irq);
295 static bool assign_slot(struct pci_irq_entry **head,
296 const struct slot_irq_constraints *constraints)
298 struct pin_info pin_info[PCI_INT_MAX] = {0};
299 enum pci_pin fn_pin_map[MAX_FNS] = {0};
301 /* The order in which pins are assigned is important in that strict constraints must
302 * be resolved first. This means fixed_int_pin -> fixed_pirq -> direct route ->
303 * shared pins -> shared pirqs
305 if (!assign_fixed_pins(constraints, pin_info, fn_pin_map))
306 return false;
308 if (!assign_fixed_pirqs(constraints, pin_info, fn_pin_map))
309 return false;
311 if (!assign_direct_irqs(constraints, pin_info, fn_pin_map))
312 return false;
314 if (!assign_shareable_pins(constraints, pin_info, fn_pin_map))
315 return false;
317 if (!assign_pirqs(pin_info))
318 return false;
320 add_slot_entries(head, constraints->slot, pin_info, fn_pin_map);
321 return true;
324 static struct pci_irq_entry *cached_entries;
326 bool assign_pci_irqs(const struct slot_irq_constraints *constraints, size_t num_slots)
328 for (size_t i = 0; i < num_slots; i++) {
329 if (!assign_slot(&cached_entries, &constraints[i]))
330 return false;
333 const struct pci_irq_entry *entry = cached_entries;
334 while (entry) {
335 printk(BIOS_INFO, "PCI %2X.%X, %s, using IRQ #%d\n",
336 PCI_SLOT(entry->devfn), PCI_FUNC(entry->devfn),
337 pin_to_str(entry->pin), entry->irq);
339 entry = entry->next;
342 return true;
345 const struct pci_irq_entry *get_cached_pci_irqs(void)
347 return cached_entries;
350 static enum pirq irq_to_pirq(unsigned int irq)
352 if (irq >= MIN_SHARED_IRQ && irq <= MAX_SHARED_IRQ)
353 return (enum pirq)(irq - MIN_SHARED_IRQ + PIRQ_A);
354 else
356 * Unknown if devices that require unique IRQs will
357 * even work in legacy PIC mode, given they cannot map
358 * to a PIRQ, therefore skip adding an entry.
360 return PIRQ_INVALID;
363 bool generate_pin_irq_map(void)
365 struct slot_pin_irq_map *pin_irq_map;
366 const uint8_t *legacy_pirq_routing;
367 struct pic_pirq_map pirq_map = {0};
368 size_t map_count = 0;
369 size_t pirq_routes;
370 size_t i;
372 if (!cached_entries)
373 return false;
375 pin_irq_map = calloc(MAX_SLOTS * PCI_INT_MAX, sizeof(struct slot_pin_irq_map));
377 pirq_map.type = PIRQ_GSI;
378 legacy_pirq_routing = lpc_get_pic_pirq_routing(&pirq_routes);
379 for (i = 0; i < PIRQ_COUNT && i < pirq_routes; i++)
380 pirq_map.gsi[i] = legacy_pirq_routing[i];
382 const struct pci_irq_entry *entry = cached_entries;
383 while (entry) {
384 const unsigned int slot = PCI_SLOT(entry->devfn);
386 if (is_slot_pin_assigned(pin_irq_map, map_count, slot, entry->pin)) {
387 entry = entry->next;
388 continue;
391 pin_irq_map[map_count].slot = slot;
392 pin_irq_map[map_count].pin = entry->pin;
393 pin_irq_map[map_count].apic_gsi = entry->irq;
394 pin_irq_map[map_count].pic_pirq = irq_to_pirq(entry->irq);
395 map_count++;
396 entry = entry->next;
399 intel_write_pci_PRT("\\_SB.PCI0", pin_irq_map, map_count, &pirq_map);
400 free(pin_irq_map);
402 return true;
405 bool __weak is_pch_slot(unsigned int devfn)
407 if (PCI_SLOT(devfn) >= MIN_PCH_SLOT)
408 return true;
409 return false;
412 bool irq_program_non_pch(void)
414 const struct pci_irq_entry *entry = cached_entries;
416 if (!entry)
417 return false;
419 while (entry) {
420 if (is_pch_slot(entry->devfn)) {
421 entry = entry->next;
422 continue;
425 if (entry->irq) {
426 pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(entry->devfn),
427 PCI_FUNC(entry->devfn));
428 pci_s_write_config8(dev, PCI_INTERRUPT_LINE, entry->irq);
429 pci_s_write_config8(dev, PCI_INTERRUPT_PIN, (uint8_t)entry->pin);
432 entry = entry->next;
435 return true;
438 int get_pci_devfn_irq(unsigned int devfn)
440 const struct pci_irq_entry *entry = cached_entries;
442 while (entry) {
443 if (entry->devfn == devfn)
444 return entry->irq;
446 entry = entry->next;
449 return INVALID_IRQ;