Angel Pons | 182dbde | 2020-04-02 23:49:05 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 2 | |
Furquan Shaikh | 76cedd2 | 2020-05-02 10:24:23 -0700 | [diff] [blame] | 3 | #include <acpi/acpigen.h> |
Tim Wawrzynczak | 53d08b6 | 2021-03-01 14:42:57 -0700 | [diff] [blame] | 4 | #include <acpi/acpigen_pci.h> |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 5 | #include <device/pci_def.h> |
Patrick Rudolph | e56189c | 2018-04-18 10:11:59 +0200 | [diff] [blame] | 6 | #include <device/pci_ops.h> |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 7 | |
| 8 | #include "acpi_pirq_gen.h" |
| 9 | |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 10 | static void gen_apic_route(const struct slot_pin_irq_map *pin_irq_map, |
| 11 | unsigned int map_count) |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 12 | { |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 13 | for (unsigned int i = 0; i < map_count; i++) |
| 14 | /* |
| 15 | * The reason for subtracting PCI_INT_A from the pin given is |
| 16 | * that PCI defines pins as 1-4, and _PRT uses 0-3. |
| 17 | */ |
| 18 | acpigen_write_PRT_GSI_entry(pin_irq_map[i].slot, |
| 19 | pin_irq_map[i].pin - PCI_INT_A, |
| 20 | pin_irq_map[i].apic_gsi); |
| 21 | } |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 22 | |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 23 | static void gen_pic_route(const struct slot_pin_irq_map *pin_irq_map, |
| 24 | unsigned int map_count, |
| 25 | const struct pic_pirq_map *pirq_map) |
| 26 | { |
| 27 | for (unsigned int i = 0; i < map_count; i++) { |
Tim Wawrzynczak | ef16df2 | 2021-06-05 11:38:14 -0600 | [diff] [blame] | 28 | const enum pirq pirq = pin_irq_map[i].pic_pirq; |
| 29 | const unsigned int pin = pin_irq_map[i].pin - PCI_INT_A; |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 30 | if (pirq == PIRQ_INVALID) |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 31 | continue; |
| 32 | |
Tim Wawrzynczak | ef16df2 | 2021-06-05 11:38:14 -0600 | [diff] [blame] | 33 | const size_t pirq_index = pirq_idx(pirq); |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 34 | if (pirq_map->type == PIRQ_GSI) |
| 35 | acpigen_write_PRT_GSI_entry(pin_irq_map[i].slot, |
| 36 | pin, |
Tim Wawrzynczak | ef16df2 | 2021-06-05 11:38:14 -0600 | [diff] [blame] | 37 | pirq_map->gsi[pirq_index]); |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 38 | else |
| 39 | acpigen_write_PRT_source_entry(pin_irq_map[i].slot, |
| 40 | pin, |
Tim Wawrzynczak | ef16df2 | 2021-06-05 11:38:14 -0600 | [diff] [blame] | 41 | pirq_map->source_path[pirq_index], |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 42 | 0); |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 43 | } |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 44 | } |
| 45 | |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 46 | void intel_write_pci0_PRT(const struct slot_pin_irq_map *pin_irq_map, |
| 47 | unsigned int map_count, |
| 48 | const struct pic_pirq_map *pirq_map) |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 49 | { |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 50 | /* \_SB.PCI0._PRT */ |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 51 | acpigen_write_scope("\\_SB.PCI0"); |
| 52 | acpigen_write_method("_PRT", 0); |
| 53 | acpigen_write_if(); |
| 54 | acpigen_emit_namestring("PICM"); |
| 55 | acpigen_emit_byte(RETURN_OP); |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 56 | acpigen_write_package(map_count); |
| 57 | gen_apic_route(pin_irq_map, map_count); |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 58 | acpigen_pop_len(); /* package */ |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 59 | acpigen_write_else(); |
| 60 | acpigen_emit_byte(RETURN_OP); |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 61 | acpigen_write_package(map_count); |
| 62 | gen_pic_route(pin_irq_map, map_count, pirq_map); |
Tobias Diedrich | 9d8be5a | 2017-12-13 23:25:32 +0100 | [diff] [blame] | 63 | acpigen_pop_len(); /* package */ |
| 64 | acpigen_pop_len(); /* else PICM */ |
| 65 | acpigen_pop_len(); /* _PRT */ |
| 66 | acpigen_pop_len(); /* \_SB */ |
| 67 | } |
Tim Wawrzynczak | f62c494 | 2021-02-26 10:30:52 -0700 | [diff] [blame] | 68 | |
| 69 | bool is_slot_pin_assigned(const struct slot_pin_irq_map *pin_irq_map, |
| 70 | unsigned int map_count, unsigned int slot, |
| 71 | enum pci_pin pin) |
| 72 | { |
| 73 | for (size_t i = 0; i < map_count; i++) { |
| 74 | if (pin_irq_map[i].slot == slot && pin_irq_map[i].pin == pin) |
| 75 | return true; |
| 76 | } |
| 77 | |
| 78 | return false; |
| 79 | } |