1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpi_device.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
9 #include <southbridge/intel/common/acpi_pirq_gen.h>
10 #include <southbridge/intel/common/rcba_pirq.h>
11 #include <southbridge/intel/common/rcba.h>
16 static const u32 pirq_dir_route_reg
[MAX_SLOT
- MIN_SLOT
+ 1] = {
17 D19IR
, D20IR
, D21IR
, D22IR
, D23IR
, 0, D25IR
,
18 D26IR
, D27IR
, D28IR
, D29IR
, D30IR
, D31IR
,
21 static enum pirq
map_pirq(const struct device
*dev
, const enum pci_pin pci_pin
)
23 u8 slot
= PCI_SLOT(dev
->path
.pci
.devfn
);
24 u8 shift
= 4 * (pci_pin
- PCI_INT_A
);
28 if (pci_pin
< PCI_INT_A
|| pci_pin
> PCI_INT_D
) {
29 printk(BIOS_ERR
, "ACPI_PIRQ_GEN: Slot %d PCI pin %d out of bounds\n",
34 /* Slot 24 should not exist and has no D24IR but better be safe here */
35 if (slot
< MIN_SLOT
|| slot
> MAX_SLOT
|| slot
== 24) {
36 /* non-PCH devices use 1:1 mapping. */
37 return (enum pirq
)pci_pin
;
40 reg
= pirq_dir_route_reg
[slot
- MIN_SLOT
];
42 pirq
= (RCBA16(reg
) >> shift
) & 0x7;
44 return (enum pirq
)(pirq
+ PIRQ_A
);
47 void intel_acpi_gen_def_acpi_pirq(const struct device
*lpc
)
49 struct slot_pin_irq_map
*pin_irq_map
;
50 const char *lpcb_path
= acpi_device_path(lpc
);
51 struct pic_pirq_map pirq_map
= {0};
52 unsigned int map_count
= 0;
56 printk(BIOS_ERR
, "ACPI_PIRQ_GEN: Missing LPCB ACPI path\n");
60 printk(BIOS_DEBUG
, "Generating ACPI PIRQ entries\n");
62 pin_irq_map
= calloc(MAX_SLOTS
* PCI_INT_MAX
, sizeof(struct slot_pin_irq_map
));
63 pirq_map
.type
= PIRQ_SOURCE_PATH
;
64 for (i
= 0; i
< PIRQ_COUNT
; i
++)
65 snprintf(pirq_map
.source_path
[i
], sizeof(pirq_map
.source_path
[i
]),
66 "%s.LNK%c", lpcb_path
, 'A' + i
);
68 for (struct device
*dev
= pcidev_on_root(0, 0); dev
; dev
= dev
->sibling
) {
69 const u8 pci_dev
= PCI_SLOT(dev
->path
.pci
.devfn
);
70 const u8 int_pin
= pci_read_config8(dev
, PCI_INTERRUPT_PIN
);
72 if (int_pin
< PCI_INT_A
|| int_pin
> PCI_INT_D
)
75 if (is_slot_pin_assigned(pin_irq_map
, map_count
, pci_dev
, int_pin
))
78 enum pirq pirq
= map_pirq(dev
, int_pin
);
79 if (pirq
== PIRQ_INVALID
)
82 pin_irq_map
[map_count
].slot
= pci_dev
;
83 pin_irq_map
[map_count
].pin
= (enum pci_pin
)int_pin
;
84 pin_irq_map
[map_count
].pic_pirq
= pirq
;
85 /* PIRQs are mapped to GSIs starting at 16 */
86 pin_irq_map
[map_count
].apic_gsi
= 16 + pirq_idx(pirq
);
87 printk(BIOS_SPEW
, "ACPI_PIRQ_GEN: %s: pin=%d pirq=%zd\n",
88 dev_path(dev
), int_pin
- PCI_INT_A
,
89 pirq_idx(pin_irq_map
[map_count
].pic_pirq
));
93 intel_write_pci0_PRT(pin_irq_map
, map_count
, &pirq_map
);