coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
rcba_pirq.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi_device.h>
4 #include <console/console.h>
5 #include <device/device.h>
6 #include <device/pci.h>
7 #include <stdlib.h>
11 
12 #define MAX_SLOT 31
13 #define MIN_SLOT 19
14 
15 static const u32 pirq_dir_route_reg[MAX_SLOT - MIN_SLOT + 1] = {
16  D19IR, D20IR, D21IR, D22IR, D23IR, 0, D25IR,
18 };
19 
20 static enum pirq map_pirq(const struct device *dev, const enum pci_pin pci_pin)
21 {
22  u8 slot = PCI_SLOT(dev->path.pci.devfn);
23  u8 shift = 4 * (pci_pin - PCI_INT_A);
24  u8 pirq;
25  u16 reg;
26 
28  printk(BIOS_ERR, "ACPI_PIRQ_GEN: Slot %d PCI pin %d out of bounds\n",
29  slot, pci_pin);
30  return PIRQ_INVALID;
31  }
32 
33  /* Slot 24 should not exist and has no D24IR but better be safe here */
34  if (slot < MIN_SLOT || slot > MAX_SLOT || slot == 24) {
35  /* non-PCH devices use 1:1 mapping. */
36  return (enum pirq)pci_pin;
37  }
38 
39  reg = pirq_dir_route_reg[slot - MIN_SLOT];
40 
41  pirq = (RCBA16(reg) >> shift) & 0x7;
42 
43  return (enum pirq)(pirq + PIRQ_A);
44 }
45 
46 void intel_acpi_gen_def_acpi_pirq(const struct device *lpc)
47 {
48  struct slot_pin_irq_map *pin_irq_map;
49  const char *lpcb_path = acpi_device_path(lpc);
50  struct pic_pirq_map pirq_map = {0};
51  unsigned int map_count = 0;
52  int i;
53 
54  if (!lpcb_path) {
55  printk(BIOS_ERR, "ACPI_PIRQ_GEN: Missing LPCB ACPI path\n");
56  return;
57  }
58 
59  printk(BIOS_DEBUG, "Generating ACPI PIRQ entries\n");
60 
61  pin_irq_map = calloc(sizeof(struct slot_pin_irq_map), MAX_SLOTS * PCI_INT_MAX);
62  pirq_map.type = PIRQ_SOURCE_PATH;
63  for (i = 0; i < PIRQ_COUNT; i++)
64  snprintf(pirq_map.source_path[i], sizeof(pirq_map.source_path[i]),
65  "%s.LNK%c", lpcb_path, 'A' + i);
66 
67  for (struct device *dev = pcidev_on_root(0, 0); dev; dev = dev->sibling) {
68  const u8 pci_dev = PCI_SLOT(dev->path.pci.devfn);
69  const u8 int_pin = pci_read_config8(dev, PCI_INTERRUPT_PIN);
70 
71  if (int_pin < PCI_INT_A || int_pin > PCI_INT_D)
72  continue;
73 
74  if (is_slot_pin_assigned(pin_irq_map, map_count, pci_dev, int_pin))
75  continue;
76 
77  enum pirq pirq = map_pirq(dev, int_pin);
78  if (pirq == PIRQ_INVALID)
79  continue;
80 
81  pin_irq_map[map_count].slot = pci_dev;
82  pin_irq_map[map_count].pin = (enum pci_pin)int_pin;
83  pin_irq_map[map_count].pic_pirq = pirq;
84  /* PIRQs are mapped to GSIs starting at 16 */
85  pin_irq_map[map_count].apic_gsi = 16 + pirq_idx(pirq);
86  printk(BIOS_SPEW, "ACPI_PIRQ_GEN: %s: pin=%d pirq=%zd\n",
87  dev_path(dev), int_pin - PCI_INT_A,
88  pirq_idx(pin_irq_map[map_count].pic_pirq));
89  map_count++;
90  }
91 
92  intel_write_pci0_PRT(pin_irq_map, map_count, &pirq_map);
93 
94  free(pin_irq_map);
95 }
const char * acpi_device_path(const struct device *dev)
Definition: device.c:144
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_INVALID
Definition: acpi_pirq_gen.h:21
@ PIRQ_COUNT
Definition: acpi_pirq_gen.h:30
@ PIRQ_SOURCE_PATH
Definition: acpi_pirq_gen.h:67
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_MAX
Definition: acpi_pirq_gen.h:17
@ PCI_INT_A
Definition: acpi_pirq_gen.h:13
#define pci_dev
#define printk(level,...)
Definition: stdlib.h:16
DEVTREE_CONST struct device * pcidev_on_root(uint8_t dev, uint8_t fn)
Definition: device_const.c:260
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
static __always_inline u8 pci_read_config8(const struct device *dev, u16 reg)
Definition: pci_ops.h:46
void * calloc(size_t nitems, size_t size)
Definition: malloc.c:58
void free(void *ptr)
Definition: malloc.c:67
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
#define PCI_INTERRUPT_PIN
Definition: pci_def.h:95
#define PCI_SLOT(devfn)
Definition: pci_def.h:549
#define MIN_SLOT
Definition: rcba_pirq.c:13
#define MAX_SLOT
Definition: rcba_pirq.c:12
void intel_acpi_gen_def_acpi_pirq(const struct device *lpc)
Definition: rcba_pirq.c:46
static const u32 pirq_dir_route_reg[MAX_SLOT - MIN_SLOT+1]
Definition: rcba_pirq.c:15
static enum pirq map_pirq(const struct device *dev, const enum pci_pin pci_pin)
Definition: rcba_pirq.c:20
#define D20IR
Definition: rcba.h:96
#define D31IR
Definition: rcba.h:87
#define D26IR
Definition: rcba.h:92
#define D30IR
Definition: rcba.h:88
#define D28IR
Definition: rcba.h:90
#define D22IR
Definition: rcba.h:95
#define D25IR
Definition: rcba.h:93
#define D29IR
Definition: rcba.h:89
#define D19IR
Definition: rcba.h:98
#define D27IR
Definition: rcba.h:91
#define D23IR
Definition: rcba.h:94
#define D21IR
Definition: rcba.h:97
#define RCBA16(x)
Definition: rcba.h:13
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
struct pci_path pci
Definition: path.h:116
Definition: device.h:107
DEVTREE_CONST struct device * sibling
Definition: device.h:111
struct device_path path
Definition: device.h:115
unsigned int devfn
Definition: path.h:54
enum pirq_map_type type
Definition: acpi_pirq_gen.h:75
char source_path[PIRQ_COUNT][DEVICE_PATH_MAX]
Definition: acpi_pirq_gen.h:78
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
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35