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